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 .
2018-04-24 13:21:53 +02:00
Copyright ( C ) 1999 - 2018 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 *********************************/
/*****************************************************************************/
# include <linux/stddef.h> // For NULL
# include <stdlib.h> // For exit, system, malloc, free, rand, etc.
# include <string.h> // For string functions
# include "swad_action.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"
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"
# include "swad_notification.h"
# include "swad_parameter.h"
2017-09-17 16:58:09 +02:00
# include "swad_project.h"
2017-06-11 20:09:59 +02:00
# include "swad_table.h"
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/*************************** Internal constants ******************************/
/*****************************************************************************/
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 ] =
{
false , // Rol_UNK
false , // Rol_GST
false , // Rol_USR
true , // Rol_STD
false , // Rol_NET
true , // Rol_TCH
false , // Rol_DEG_ADM
false , // Rol_CTR_ADM
false , // Rol_INS_ADM
true , // Rol_SYS_ADM
} ;
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/***************************** Internal types ********************************/
/*****************************************************************************/
/*****************************************************************************/
/************* External global variables from others modules *****************/
/*****************************************************************************/
extern struct Globals Gbl ;
/*****************************************************************************/
/************************* Internal global variables *************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Internal prototypes ***************************/
/*****************************************************************************/
2017-05-11 23:45:46 +02:00
static void Grp_ReqEditGroupsInternal ( Ale_AlertType_t AlertTypeGroupTypes , const char * MessageGroupTypes ,
Ale_AlertType_t AlertTypeGroups , const char * MessageGroups ) ;
2017-04-29 02:20:34 +02:00
static void Grp_ReqEditGroupsInternal0 ( void ) ;
2017-05-11 23:45:46 +02:00
static void Grp_ReqEditGroupsInternal1 ( Ale_AlertType_t AlertTypeGroupTypes , const char * MessageGroupTypes ) ;
static void Grp_ReqEditGroupsInternal2 ( Ale_AlertType_t AlertTypeGroups , const char * MessageGroups ) ;
2017-04-28 18:03:30 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_EditGroupTypes ( void ) ;
static void Grp_EditGroups ( void ) ;
2017-04-29 20:16:53 +02:00
static void Grp_PutIconsEditingGroups ( void ) ;
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 ) ;
static void Grp_AddUsrToGroup ( struct UsrData * UsrDat , long GrpCod ) ;
2017-04-29 19:32:06 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_ListGroupTypesForEdition ( void ) ;
2017-04-29 19:19:55 +02:00
static void Grp_PutIconsEditingGroupTypes ( void ) ;
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
2014-12-01 23:55:08 +01:00
static void Grp_ListGroupsForEdition ( void ) ;
static void Grp_WriteHeadingGroups ( void ) ;
2016-03-16 22:40:35 +01:00
static void Grp_PutIconToEditGroups ( void ) ;
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 ) ;
static void Grp_PutFormToCreateGroup ( void ) ;
static unsigned Grp_CountNumGrpsInThisCrsOfType ( long GrpTypCod ) ;
static void Grp_GetDataOfGroupTypeByCod ( struct GroupType * GrpTyp ) ;
2017-03-30 11:20:06 +02:00
static bool Grp_GetMultipleEnrolmentOfAGroupType ( long GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
static long Grp_GetTypeOfGroupOfAGroup ( long GrpCod ) ;
2017-05-30 21:43:05 +02:00
static unsigned Grp_CountNumUsrsInNoGrpsOfType ( Rol_Role_t Role , long GrpTypCod ) ;
2017-06-20 01:58:16 +02:00
static long Grp_GetFirstCodGrpIBelongTo ( long GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
static bool Grp_GetIfGrpIsAvailable ( long GrpTypCod ) ;
static void Grp_GetLstCodGrpsUsrBelongs ( long CrsCod , long GrpTypCod , long UsrCod ,
struct ListCodGrps * LstGrps ) ;
static bool Grp_CheckIfGrpIsInList ( long GrpCod , struct ListCodGrps * LstGrps ) ;
2015-10-26 20:02:07 +01:00
static bool Grp_CheckIfOpenTimeInTheFuture ( time_t OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
static bool Grp_CheckIfGroupTypeNameExists ( const char * GrpTypName , long GrpTypCod ) ;
static bool Grp_CheckIfGroupNameExists ( long GrpTypCod , const char * GrpName , long GrpCod ) ;
static void Grp_CreateGroupType ( void ) ;
static void Grp_CreateGroup ( void ) ;
2017-04-28 13:10:46 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_AskConfirmRemGrpTypWithGrps ( unsigned NumGrps ) ;
2017-04-28 14:12:37 +02:00
static void Grp_PutParamRemGrpTyp ( void ) ;
2014-12-01 23:55:08 +01:00
static void Grp_AskConfirmRemGrp ( void ) ;
2017-04-28 13:10:46 +02:00
static void Grp_PutParamRemGrp ( void ) ;
2014-12-01 23:55:08 +01:00
static void Grp_RemoveGroupTypeCompletely ( void ) ;
static void Grp_RemoveGroupCompletely ( void ) ;
2017-04-28 13:10:46 +02:00
2014-12-01 23:55:08 +01:00
static void Grp_WriteMaxStdsGrp ( unsigned MaxStudents ) ;
static long Grp_GetParamGrpTypCod ( void ) ;
static long Grp_GetParamGrpCod ( void ) ;
static void Grp_PutParamGrpTypCod ( long GrpTypCod ) ;
/*****************************************************************************/
/******************* Write the names of the selected groups ******************/
/*****************************************************************************/
void Grp_WriteNamesOfSelectedGrps ( void )
{
extern const char * Txt_Group ;
extern const char * Txt_Groups ;
2017-05-30 21:43:05 +02:00
extern const char * Txt_users_with_no_group ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_and ;
long GrpCod ;
unsigned NumGrpSel ;
struct GroupData GrpDat ;
/***** Show the selected groups *****/
fprintf ( Gbl . F . Out , " %s: " ,
( Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps = = 1 ) ?
Txt_Group :
Txt_Groups ) ;
for ( NumGrpSel = 0 ;
NumGrpSel < Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps ;
NumGrpSel + + )
{
2017-01-19 20:55:31 +01:00
if ( ( GrpCod = Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods [ NumGrpSel ] ) > = 0 )
2014-12-01 23:55:08 +01:00
{
GrpDat . GrpCod = GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
fprintf ( Gbl . F . Out , " %s %s " ,
GrpDat . GrpTypName , GrpDat . GrpName ) ;
}
else // GrpCod < 0 ==> students not belonging to any group of type (-GrpCod)
{
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = - GrpCod ;
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
fprintf ( Gbl . F . Out , " %s (%s) " ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ,
2017-05-30 21:43:05 +02:00
Txt_users_with_no_group ) ;
2014-12-01 23:55:08 +01:00
}
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps > = 2 )
{
if ( NumGrpSel = = Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps - 2 )
fprintf ( Gbl . F . Out , " %s " , Txt_and ) ;
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps > = 3 )
if ( NumGrpSel < Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps - 2 )
fprintf ( Gbl . F . Out , " , " ) ;
}
}
}
/*****************************************************************************/
/************************** 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
}
2017-05-11 23:45:46 +02:00
static void Grp_ReqEditGroupsInternal ( Ale_AlertType_t AlertTypeGroupTypes , const char * MessageGroupTypes ,
Ale_AlertType_t AlertTypeGroups , const char * MessageGroups )
2017-04-28 18:03:30 +02:00
{
2017-04-29 02:20:34 +02:00
Grp_ReqEditGroupsInternal0 ( ) ;
2017-04-29 20:42:10 +02:00
Grp_ReqEditGroupsInternal1 ( AlertTypeGroupTypes , MessageGroupTypes ) ;
Grp_ReqEditGroupsInternal2 ( AlertTypeGroups , MessageGroups ) ;
2017-04-28 18:03:30 +02:00
}
2017-04-29 02:20:34 +02:00
static void Grp_ReqEditGroupsInternal0 ( void )
2017-04-29 00:23:48 +02:00
{
2017-04-29 02:20:34 +02:00
/***** Start groups types section *****/
2017-05-25 13:43:54 +02:00
Lay_StartSection ( Grp_GROUP_TYPES_SECTION_ID ) ;
2017-04-29 00:23:48 +02:00
}
2017-05-11 23:45:46 +02:00
static void Grp_ReqEditGroupsInternal1 ( Ale_AlertType_t AlertTypeGroupTypes , const char * MessageGroupTypes )
2014-12-01 23:55:08 +01:00
{
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ALL_GROUP_TYPES ) ;
2017-04-29 02:20:34 +02:00
/***** Show optional alert *****/
2017-04-29 20:42:10 +02:00
if ( MessageGroupTypes )
if ( MessageGroupTypes [ 0 ] )
2017-05-11 23:45:46 +02:00
Ale_ShowAlert ( AlertTypeGroupTypes , MessageGroupTypes ) ;
2017-04-28 18:03:30 +02:00
2017-04-29 02:20:34 +02:00
/***** Put form to edit group types *****/
2014-12-01 23:55:08 +01:00
Grp_EditGroupTypes ( ) ;
2017-04-29 02:20:34 +02:00
/***** End groups types section *****/
2017-05-25 13:43:54 +02:00
Lay_EndSection ( ) ;
2017-04-28 18:03:30 +02:00
2017-04-29 02:20:34 +02:00
/***** Start groups section *****/
2017-05-25 13:43:54 +02:00
Lay_StartSection ( Grp_GROUPS_SECTION_ID ) ;
2017-04-29 00:23:48 +02:00
}
2017-04-28 18:03:30 +02:00
2017-05-11 23:45:46 +02:00
static void Grp_ReqEditGroupsInternal2 ( Ale_AlertType_t AlertTypeGroups , const char * MessageGroups )
2017-04-29 00:23:48 +02:00
{
2017-04-29 02:20:34 +02:00
/***** Show optional alert *****/
2017-04-29 20:42:10 +02:00
if ( MessageGroups )
if ( MessageGroups [ 0 ] )
2017-05-11 23:45:46 +02:00
Ale_ShowAlert ( AlertTypeGroups , MessageGroups ) ;
2017-04-29 02:20:34 +02:00
/***** Put form to edit groups *****/
2014-12-01 23:55:08 +01:00
if ( Gbl . CurrentCrs . Grps . GrpTypes . Num ) // If there are group types...
Grp_EditGroups ( ) ;
2017-04-29 02:20:34 +02:00
/***** End groups section *****/
2017-05-25 13:43:54 +02:00
Lay_EndSection ( ) ;
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 ;
2017-06-12 14:16:33 +02:00
/***** Start box *****/
2017-06-11 22:26:40 +02:00
Box_StartBox ( NULL , Txt_Types_of_group , Grp_PutIconsEditingGroupTypes ,
2017-06-12 15:03:29 +02:00
Hlp_USERS_Groups , Box_NOT_CLOSABLE ) ;
2017-04-29 20:16:53 +02:00
2017-05-11 14:47:48 +02:00
/***** Put a form to create a new group type *****/
Grp_PutFormToCreateGroupType ( ) ;
2014-12-01 23:55:08 +01:00
/***** Forms to edit current group types *****/
if ( Gbl . CurrentCrs . Grps . GrpTypes . Num ) // Group types found...
Grp_ListGroupTypesForEdition ( ) ;
else // No group types found in this course
{
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_There_are_no_types_of_group_in_the_course_X ,
Gbl . CurrentCrs . Crs . ShrtName ) ;
2017-05-11 23:45:46 +02:00
Ale_ShowAlert ( Ale_INFO , Gbl . Alert . Txt ) ;
2014-12-01 23:55:08 +01:00
}
2017-06-12 14:16:33 +02:00
/***** End box *****/
2017-06-10 21:38:10 +02:00
Box_EndBox ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/**************************** Put forms to edit groups ***********************/
/*****************************************************************************/
static void Grp_EditGroups ( void )
{
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 ;
2017-06-12 14:16:33 +02:00
/***** Start box *****/
2017-06-10 21:38:10 +02:00
Box_StartBox ( NULL , Txt_Groups , Grp_PutIconsEditingGroups ,
2017-06-12 15:03:29 +02:00
Hlp_USERS_Groups , Box_NOT_CLOSABLE ) ;
2017-04-29 20:16:53 +02:00
2017-05-11 14:47:48 +02:00
/***** Put a form to create a new group *****/
Grp_PutFormToCreateGroup ( ) ;
2014-12-01 23:55:08 +01:00
/***** Forms to edit current groups *****/
if ( Gbl . CurrentCrs . Grps . GrpTypes . NumGrpsTotal ) // If there are groups...
Grp_ListGroupsForEdition ( ) ;
else // There are group types, but there aren't groups
{
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_No_groups_have_been_created_in_the_course_X ,
Gbl . CurrentCrs . Crs . ShrtName ) ;
2017-05-11 23:45:46 +02:00
Ale_ShowAlert ( Ale_INFO , Gbl . Alert . Txt ) ;
2014-12-01 23:55:08 +01:00
}
2017-06-12 14:16:33 +02:00
/***** End box *****/
2017-06-10 21:38:10 +02:00
Box_EndBox ( ) ;
2017-04-29 20:16:53 +02:00
}
/*****************************************************************************/
/**************** Put contextual icons in edition of groups ******************/
/*****************************************************************************/
static void Grp_PutIconsEditingGroups ( void )
{
/***** Put icon to view groups *****/
Grp_PutIconToViewGroups ( ) ;
/***** Put icon to create a new group *****/
Grp_PutIconToCreateNewGroup ( ) ;
}
static void Grp_PutIconToCreateNewGroup ( void )
{
extern const char * Txt_New_group ;
/***** Put form to create a new group *****/
2017-05-25 13:43:54 +02:00
Lay_PutContextualLink ( ActReqEdiGrp , Grp_NEW_GROUP_SECTION_ID , NULL ,
2017-04-29 20:16:53 +02:00
" plus64x64.png " ,
Txt_New_group , NULL ,
NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*************** Show form to select one or several groups *******************/
/*****************************************************************************/
2017-07-02 18:53:35 +02:00
void Grp_ShowFormToSelectSeveralGroups ( Act_Action_t NextAction ,
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-07-27 21:25:45 +02:00
extern const char * The_ClassFormBold [ The_NUM_THEMES ] ;
2015-04-11 14:27:18 +02:00
extern const char * Txt_Groups ;
2017-05-30 18:24:26 +02:00
extern const char * Txt_Update_users_according_to_selected_groups ;
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
2016-11-25 03:21:02 +01:00
if ( Gbl . CurrentCrs . Grps . NumGrps )
{
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 ) ;
2016-11-25 03:21:02 +01:00
2017-06-12 14:16:33 +02:00
/***** Start box *****/
2017-06-11 22:26:40 +02:00
Box_StartBox ( NULL , Txt_Groups , ICanEdit ? Grp_PutIconToEditGroups :
NULL ,
2017-06-12 15:03:29 +02:00
Hlp_USERS_Groups , Box_CLOSABLE ) ;
2016-11-25 03:21:02 +01:00
/***** Start form to update the students listed
depending on the groups selected * * * * */
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( NextAction , Usr_USER_LIST_SECTION_ID ) ;
2017-02-01 11:23:48 +01:00
Usr_PutParamsPrefsAboutUsrList ( ) ;
2016-11-25 03:21:02 +01:00
/***** Put parameters needed depending on the action *****/
Usr_PutExtraParamsUsrList ( NextAction ) ;
/***** Select all groups *****/
2017-07-02 18:53:35 +02:00
Grp_PutCheckboxAllGrps ( GroupsSelectableByStdsOrNETs ) ;
2016-11-25 03:21:02 +01:00
/***** Get list of groups types and groups in this course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
/***** List the groups for each group type *****/
2017-06-11 20:09:59 +02:00
Tbl_StartTableWide ( 2 ) ;
2016-11-25 03:21:02 +01:00
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps )
2017-06-23 09:56:01 +02:00
Grp_ListGrpsForMultipleSelection ( & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ,
2017-07-02 18:53:35 +02:00
GroupsSelectableByStdsOrNETs ) ;
2017-06-11 20:09:59 +02:00
Tbl_EndTable ( ) ;
2016-11-25 03:21:02 +01:00
/***** Free list of groups types and groups in this course *****/
Grp_FreeListGrpTypesAndGrps ( ) ;
/***** Submit button *****/
fprintf ( Gbl . F . Out , " <div class= \" CENTER_MIDDLE \" "
" style= \" padding-top:12px; \" > " ) ;
2017-05-30 18:24:26 +02:00
Act_LinkFormSubmitAnimated ( Txt_Update_users_according_to_selected_groups ,
2016-11-25 03:21:02 +01:00
The_ClassFormBold [ Gbl . Prefs . Theme ] ,
" CopyMessageToHiddenFields() " ) ;
2017-06-11 19:13:28 +02:00
Ico_PutCalculateIconWithText ( Txt_Update_users_according_to_selected_groups ,
2017-05-30 18:24:26 +02:00
Txt_Update_users ) ;
2016-11-25 03:21:02 +01:00
fprintf ( Gbl . F . Out , " </div> " ) ;
/***** End form *****/
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2016-11-25 03:21:02 +01:00
2017-06-12 14:16:33 +02:00
/***** End box *****/
2017-06-10 21:38:10 +02:00
Box_EndBox ( ) ;
2016-11-25 03:21:02 +01:00
}
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 * The_ClassForm [ The_NUM_THEMES ] ;
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
fprintf ( Gbl . F . Out , " <div class= \" CONTEXT_OPT \" > "
" <label class= \" %s \" > "
" <input type= \" checkbox \" "
" id= \" AllGroups \" name= \" AllGroups \" value= \" Y \" " ,
The_ClassForm [ Gbl . Prefs . Theme ] ) ;
2017-06-06 20:27:46 +02:00
if ( ICanSelUnselGroup )
{
if ( Gbl . Usrs . ClassPhoto . AllGroups )
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
fprintf ( Gbl . F . Out , " onclick= \" togglecheckChildren(this,'GrpCods') \" " ) ;
}
else
fprintf ( Gbl . F . Out , " disabled= \" disabled \" " ) ;
fprintf ( Gbl . F . Out , " /> "
2017-05-30 19:42:10 +02:00
" %s "
" </label> "
" </div> " ,
Txt_All_groups ) ;
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************ Put parameters with the groups of students selected ************/
/*****************************************************************************/
void Grp_PutParamsCodGrps ( void )
{
unsigned NumGrpSel ;
/***** Write the boolean parameter that indicates if all the groups must be listed *****/
Par_PutHiddenParamChar ( " AllGroups " ,
Gbl . Usrs . ClassPhoto . AllGroups ? ' Y ' :
' N ' ) ;
/***** Write the parameter with the list of group codes to show *****/
if ( ! Gbl . Usrs . ClassPhoto . AllGroups & &
Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps )
{
fprintf ( Gbl . F . Out , " <input type= \" hidden \" name= \" GrpCods \" value= \" " ) ;
for ( NumGrpSel = 0 ;
NumGrpSel < Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps ;
NumGrpSel + + )
{
if ( NumGrpSel )
fprintf ( Gbl . F . Out , " %c " , Par_SEPARATOR_PARAM_MULTIPLE ) ;
2017-01-19 20:55:31 +01:00
fprintf ( Gbl . F . Out , " %ld " , Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods [ NumGrpSel ] ) ;
2014-12-01 23:55:08 +01:00
}
fprintf ( Gbl . F . Out , " \" /> " ) ;
}
}
/*****************************************************************************/
/**************** Get parameters related to groups selected ******************/
/*****************************************************************************/
void Grp_GetParCodsSeveralGrpsToShowUsrs ( void )
{
struct ListCodGrps LstGrpsIBelong ;
unsigned NumGrp ;
if ( + + Gbl . CurrentCrs . Grps . LstGrpsSel . NestedCalls > 1 ) // If list is created yet, there's nothing to do
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
2017-01-19 20:55:31 +01:00
if ( Gbl . CurrentCrs . Grps . NumGrps & & // This course has groups and...
! Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps ) // ...I haven't selected any group
{
/***** 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 */
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , - 1L ,
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
if ( LstGrpsIBelong . NumGrps )
{
/* Allocate space for list of selected groups */
if ( ( Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods = ( long * ) calloc ( LstGrpsIBelong . NumGrps , sizeof ( long ) ) ) = = NULL )
Lay_ShowErrorAndExit ( " Not enough memory to store the codes of the selected groups. " ) ;
/* Fill list of selected groups with list of groups I belong to */
for ( NumGrp = 0 ;
NumGrp < LstGrpsIBelong . NumGrps ;
NumGrp + + )
Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods [ NumGrp ] = LstGrpsIBelong . GrpCods [ NumGrp ] ;
Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps = LstGrpsIBelong . NumGrps ;
}
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 *****/
if ( ! Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps )
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 ;
2017-01-19 20:55:31 +01:00
char LongStr [ 1 + 10 + 1 ] ;
2014-12-01 23:55:08 +01:00
unsigned NumGrp ;
2017-01-19 20:55:31 +01:00
unsigned long MaxSizeLstGrpCods = ( ( 1 + 10 + 1 ) * Gbl . CurrentCrs . Grps . NumGrps ) - 1 ;
2014-12-01 23:55:08 +01:00
2017-01-19 20:55:31 +01:00
/***** Reset number of groups selected *****/
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps = 0 ;
2017-01-19 20:55:31 +01:00
if ( Gbl . CurrentCrs . Grps . NumGrps ) // If course has groups
2014-12-01 23:55:08 +01:00
{
2017-01-19 20:55:31 +01:00
/***** Allocate memory for the list of group codes selected *****/
if ( ( ParamLstCodGrps = ( char * ) malloc ( MaxSizeLstGrpCods + 1 ) ) = = NULL )
Lay_ShowErrorAndExit ( " Not enough memory to store the codes of the selected groups. " ) ;
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 + + )
2017-01-28 15:58:46 +01:00
Par_GetNextStrUntilSeparParamMult ( & Ptr , LongStr , 1 + 10 ) ;
2017-01-19 20:55:31 +01:00
Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps = NumGrp ;
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps ) // If I have selected groups...
{
/***** Create a list of groups selected from LstCodGrps *****/
if ( ( Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods = ( long * ) calloc ( Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps , sizeof ( long ) ) ) = = NULL )
Lay_ShowErrorAndExit ( " Not enough memory to store the codes of the selected groups. " ) ;
for ( Ptr = ParamLstCodGrps , NumGrp = 0 ;
* Ptr ;
NumGrp + + )
{
2017-01-28 15:58:46 +01:00
Par_GetNextStrUntilSeparParamMult ( & Ptr , LongStr , 1 + 10 ) ;
2017-01-19 20:55:31 +01:00
Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods [ NumGrp ] = Str_ConvertStrCodToLongCod ( LongStr ) ;
}
}
}
2014-12-01 23:55:08 +01:00
/***** Free memory used for the list of groups to show *****/
2017-01-19 20:55:31 +01:00
free ( ( void * ) ParamLstCodGrps ) ;
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/********* Free memory used for the list of group codes selected *************/
/*****************************************************************************/
void Grp_FreeListCodSelectedGrps ( void )
{
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . NestedCalls > 0 )
if ( - - Gbl . CurrentCrs . Grps . LstGrpsSel . NestedCalls = = 0 )
2017-01-19 20:55:31 +01:00
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods )
2014-12-01 23:55:08 +01:00
{
2017-01-19 20:55:31 +01:00
free ( ( void * ) Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods ) ;
Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods = NULL ;
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps = 0 ;
}
}
/*****************************************************************************/
/******************* 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 )
{
Gbl . Alert . Type = Ale_SUCCESS ;
2018-10-16 15:16:32 +02:00
Str_Copy ( Gbl . Alert . Txt , Txt_The_requested_group_changes_were_successful ,
Ale_MAX_BYTES_ALERT ) ;
2017-06-04 18:18:54 +02:00
}
else
{
Gbl . Alert . Type = Ale_WARNING ;
2018-10-16 15:16:32 +02:00
Str_Copy ( Gbl . Alert . Txt , Txt_There_has_been_no_change_in_groups ,
Ale_MAX_BYTES_ALERT ) ;
2017-06-04 18:18:54 +02:00
}
}
}
else if ( QuietOrVerbose = = Cns_VERBOSE )
{
Gbl . Alert . Type = Ale_WARNING ;
2018-10-16 15:16:32 +02:00
Str_Copy ( Gbl . Alert . Txt , Txt_In_a_type_of_group_with_single_enrolment_students_can_not_be_registered_in_more_than_one_group ,
Ale_MAX_BYTES_ALERT ) ;
2017-06-04 18:18:54 +02:00
}
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Free memory with the list of groups which I want to belong to *****/
Grp_FreeListCodGrp ( & LstGrpsIWant ) ;
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************** Change groups of another user ************************/
/*****************************************************************************/
void Grp_ChangeOtherUsrGrps ( void )
{
extern const char * Txt_The_requested_group_changes_were_successful ;
extern const char * Txt_There_has_been_no_change_in_groups ;
2017-03-30 11:20:06 +02:00
extern const char * Txt_In_a_type_of_group_with_single_enrolment_students_can_not_be_registered_in_more_than_one_group ;
2014-12-01 23:55:08 +01:00
struct ListCodGrps LstGrpsUsrWants ;
2017-06-20 01:58:16 +02:00
bool SelectionIsValid ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Can I change another user's groups? *****/
if ( Grp_ICanChangeGrps [ Gbl . Usrs . Me . Role . Logged ] )
{
/***** Get list of groups types and groups in current course *****/
Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_ONLY_GROUP_TYPES_WITH_GROUPS ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Get the list of groups to which register this user *****/
LstGrpsUsrWants . GrpCods = NULL ; // Initialized to avoid bug reported by Coverity
LstGrpsUsrWants . NumGrps = 0 ; // Initialized to avoid bug reported by Coverity
Grp_GetLstCodsGrpWanted ( & LstGrpsUsrWants ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** A student can not be enroled in more than one group
if the type of group is of single enrolment * * * * */
2017-06-20 01:58:16 +02:00
SelectionIsValid = Grp_CheckIfSelectionGrpsSingleEnrolmentIsValid ( Gbl . Usrs . Other . UsrDat . Roles . InCurrentCrs . Role , & LstGrpsUsrWants ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Free list of groups types and groups in this course *****/
// The lists of group types and groups need to be freed here...
// ...in order to get them again when changing groups atomically
Grp_FreeListGrpTypesAndGrps ( ) ;
2014-12-01 23:55:08 +01:00
2017-06-04 18:18:54 +02:00
/***** Register user in the selected groups *****/
if ( SelectionIsValid )
Grp_ChangeGrpsOtherUsrAtomically ( & LstGrpsUsrWants ) ;
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 *****/
DB_Query ( " LOCK TABLES crs_grp_types WRITE,crs_grp WRITE, "
" crs_grp_usr WRITE,crs_usr READ " ,
" Can not lock tables to change user's groups " ) ;
Gbl . DB . LockedTables = true ;
/***** 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 *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , - 1L ,
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
2017-06-04 18:18:54 +02:00
if ( Gbl . Usrs . Me . Role . Logged = = Rol_STD )
2014-12-01 23:55:08 +01:00
{
/***** Go across the list of groups which I belong to and check if I try to leave a closed group *****/
for ( NumGrpIBelong = 0 ;
NumGrpIBelong < LstGrpsIBelong . NumGrps & & ! ITryToLeaveAClosedGroup ;
NumGrpIBelong + + )
{
for ( NumGrpIWant = 0 , RemoveMeFromThisGrp = true ;
NumGrpIWant < LstGrpsIWant - > NumGrps & & RemoveMeFromThisGrp ;
NumGrpIWant + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsIBelong . GrpCods [ NumGrpIBelong ] = = LstGrpsIWant - > GrpCods [ NumGrpIWant ] )
2014-12-01 23:55:08 +01:00
RemoveMeFromThisGrp = false ;
if ( RemoveMeFromThisGrp )
/* Check if the group is closed */
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num & & ! ITryToLeaveAClosedGroup ;
NumGrpTyp + + )
{
GrpTyp = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
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 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num & &
! ITryToRegisterInAClosedGroup & &
! ITryToRegisterInFullGroup ;
NumGrpTyp + + )
{
GrpTyp = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps & &
! ITryToRegisterInAClosedGroup & &
! ITryToRegisterInFullGroup ;
NumGrpThisType + + )
2017-01-19 20:55:31 +01:00
if ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . GrpCod = = LstGrpsIWant - > GrpCods [ NumGrpIWant ] )
2014-12-01 23:55:08 +01:00
{
/* Check if the group is closed */
if ( ! ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . Open ) )
ITryToRegisterInAClosedGroup = true ;
/* Check if the group is full */
2017-05-30 21:43:05 +02:00
else if ( ( GrpTyp - > LstGrps [ NumGrpThisType ] ) . NumUsrs [ Rol_STD ] > =
2014-12-01 23:55:08 +01:00
( GrpTyp - > LstGrps [ NumGrpThisType ] ) . MaxStudents )
ITryToRegisterInFullGroup = true ;
}
}
}
}
if ( ! ITryToLeaveAClosedGroup & &
! ITryToRegisterInAClosedGroup & &
! ITryToRegisterInFullGroup )
{
/***** Go across the list of groups I belong to, removing those groups that are not present in the list of groups I want to belong to *****/
for ( NumGrpIBelong = 0 ;
NumGrpIBelong < LstGrpsIBelong . NumGrps ;
NumGrpIBelong + + )
{
for ( NumGrpIWant = 0 , RemoveMeFromThisGrp = true ;
NumGrpIWant < LstGrpsIWant - > NumGrps & & RemoveMeFromThisGrp ;
NumGrpIWant + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsIBelong . GrpCods [ NumGrpIBelong ] = = LstGrpsIWant - > GrpCods [ NumGrpIWant ] )
2014-12-01 23:55:08 +01:00
RemoveMeFromThisGrp = false ;
if ( RemoveMeFromThisGrp )
2017-01-19 20:55:31 +01:00
Grp_RemoveUsrFromGroup ( Gbl . Usrs . Me . UsrDat . UsrCod , LstGrpsIBelong . GrpCods [ NumGrpIBelong ] ) ;
2014-12-01 23:55:08 +01:00
}
/***** Go across the list of groups that I want to register in, adding those groups that are not present in the list of groups I belong to *****/
for ( NumGrpIWant = 0 ;
NumGrpIWant < LstGrpsIWant - > NumGrps ;
NumGrpIWant + + )
{
for ( NumGrpIBelong = 0 , RegisterMeInThisGrp = true ;
NumGrpIBelong < LstGrpsIBelong . NumGrps & & RegisterMeInThisGrp ;
NumGrpIBelong + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsIWant - > GrpCods [ NumGrpIWant ] = = LstGrpsIBelong . GrpCods [ NumGrpIBelong ] )
2014-12-01 23:55:08 +01:00
RegisterMeInThisGrp = false ;
if ( RegisterMeInThisGrp )
2017-01-19 20:55:31 +01:00
Grp_AddUsrToGroup ( & Gbl . Usrs . Me . UsrDat , LstGrpsIWant - > GrpCods [ NumGrpIWant ] ) ;
2014-12-01 23:55:08 +01:00
}
ChangesMade = true ;
}
/***** Free memory with the list of groups which I belonged to *****/
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
/***** Unlock tables after changes in my groups *****/
Gbl . DB . LockedTables = false ; // Set to false before the following unlock...
2017-09-11 19:06:46 +02:00
// ...to not retry the unlock if error in unlocking
2014-12-01 23:55:08 +01:00
DB_Query ( " UNLOCK TABLES " ,
" Can not unlock tables after changes in user's groups " ) ;
/***** 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 ;
2017-06-08 15:32:33 +02:00
if ( Gbl . Usrs . Other . UsrDat . Roles . InCurrentCrs . Role = = Rol_STD )
2014-12-01 23:55:08 +01:00
{
/***** Lock tables to make the inscription atomic *****/
DB_Query ( " LOCK TABLES crs_grp_types WRITE,crs_grp WRITE, "
" crs_grp_usr WRITE,crs_usr READ " ,
" Can not lock tables to change user's groups " ) ;
Gbl . DB . LockedTables = true ;
}
/***** 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 *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , - 1L ,
Gbl . Usrs . Other . UsrDat . UsrCod , & LstGrpsUsrBelongs ) ;
/***** Go across the list of groups user belongs to, removing those groups that are not present in the list of groups user wants to belong to *****/
for ( NumGrpUsrBelongs = 0 ;
NumGrpUsrBelongs < LstGrpsUsrBelongs . NumGrps ;
NumGrpUsrBelongs + + )
{
for ( NumGrpUsrWants = 0 , RemoveUsrFromThisGrp = true ;
NumGrpUsrWants < LstGrpsUsrWants - > NumGrps & & RemoveUsrFromThisGrp ;
NumGrpUsrWants + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsUsrBelongs . GrpCods [ NumGrpUsrBelongs ] = = LstGrpsUsrWants - > GrpCods [ NumGrpUsrWants ] )
2014-12-01 23:55:08 +01:00
RemoveUsrFromThisGrp = false ;
if ( RemoveUsrFromThisGrp )
2017-01-19 20:55:31 +01:00
Grp_RemoveUsrFromGroup ( Gbl . Usrs . Other . UsrDat . UsrCod , LstGrpsUsrBelongs . GrpCods [ NumGrpUsrBelongs ] ) ;
2014-12-01 23:55:08 +01:00
}
/***** Go across the list of groups that user wants to register in, adding those groups that are not present in the list of groups user belongs to *****/
for ( NumGrpUsrWants = 0 ;
NumGrpUsrWants < LstGrpsUsrWants - > NumGrps ;
NumGrpUsrWants + + )
{
for ( NumGrpUsrBelongs = 0 , RegisterUsrInThisGrp = true ;
NumGrpUsrBelongs < LstGrpsUsrBelongs . NumGrps & & RegisterUsrInThisGrp ;
NumGrpUsrBelongs + + )
2017-01-19 20:55:31 +01:00
if ( LstGrpsUsrWants - > GrpCods [ NumGrpUsrWants ] = = LstGrpsUsrBelongs . GrpCods [ NumGrpUsrBelongs ] )
2014-12-01 23:55:08 +01:00
RegisterUsrInThisGrp = false ;
if ( RegisterUsrInThisGrp )
2017-01-19 20:55:31 +01:00
Grp_AddUsrToGroup ( & Gbl . Usrs . Other . UsrDat , LstGrpsUsrWants - > GrpCods [ NumGrpUsrWants ] ) ;
2014-12-01 23:55:08 +01:00
}
/***** Free memory with the list of groups which I belonged to *****/
Grp_FreeListCodGrp ( & LstGrpsUsrBelongs ) ;
/***** Unlock tables after changes in my groups *****/
2017-06-08 15:32:33 +02:00
if ( Gbl . Usrs . Other . UsrDat . Roles . InCurrentCrs . Role = = Rol_STD )
2014-12-01 23:55:08 +01:00
{
Gbl . DB . LockedTables = false ; // Set to false before the following unlock...
2017-09-11 19:06:46 +02:00
// ...to not retry the unlock if error in unlocking
2014-12-01 23:55:08 +01:00
DB_Query ( " UNLOCK TABLES " ,
" Can not unlock tables after changes in user's groups " ) ;
}
/***** 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 + + )
{
GrpTypCod = Grp_GetTypeOfGroupOfAGroup ( LstGrps - > GrpCods [ NumCodGrp ] ) ;
MultipleEnrolment = Grp_GetMultipleEnrolmentOfAGroupType ( GrpTypCod ) ;
if ( ! MultipleEnrolment )
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
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 *****/
if ( ( * AlreadyExistsGroupOfType = ( struct ListGrpsAlreadySelec * ) calloc ( Gbl . CurrentCrs . Grps . GrpTypes . Num , sizeof ( struct ListGrpsAlreadySelec ) ) ) = = NULL )
Lay_ShowErrorAndExit ( " Not enough memory to store type of group. " ) ;
/***** Initialize the list *****/
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
( * AlreadyExistsGroupOfType ) [ NumGrpTyp ] . GrpTypCod = Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ;
( * AlreadyExistsGroupOfType ) [ NumGrpTyp ] . AlreadySelected = false ;
}
}
/*****************************************************************************/
/***************** Liberar list of groups already selected *******************/
/*****************************************************************************/
static void Grp_DestructorListGrpAlreadySelec ( struct ListGrpsAlreadySelec * * AlreadyExistsGroupOfType )
{
free ( ( void * ) * AlreadyExistsGroupOfType ) ;
* AlreadyExistsGroupOfType = NULL ;
}
/*****************************************************************************/
/******************* Register user in the groups of a list *******************/
/*****************************************************************************/
void Grp_RegisterUsrIntoGroups ( struct UsrData * UsrDat , struct ListCodGrps * LstGrps )
{
extern const char * Txt_THE_USER_X_has_been_removed_from_the_group_of_type_Y_to_which_it_belonged ;
2017-03-30 11:20:06 +02:00
extern const char * Txt_THE_USER_X_has_been_enroled_in_the_group_of_type_Y_Z ;
2014-12-01 23:55:08 +01:00
struct ListCodGrps LstGrpsHeBelongs ;
2016-12-29 22:19:46 +01:00
unsigned NumGrpTyp ;
unsigned NumGrpSel ;
unsigned NumGrpThisType ;
unsigned NumGrpHeBelongs ;
2017-03-30 11:20:06 +02:00
bool MultipleEnrolment ;
2014-12-01 23:55:08 +01:00
bool AlreadyRegisteredInGrp ;
/***** For each existing type of group in the course... *****/
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
2017-03-30 11:20:06 +02:00
MultipleEnrolment = Gbl . CurrentCrs . 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
2014-12-01 23:55:08 +01:00
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ,
UsrDat - > UsrCod , & LstGrpsHeBelongs ) ;
/***** For each group selected by me... *****/
for ( NumGrpSel = 0 ;
NumGrpSel < LstGrps - > NumGrps ;
NumGrpSel + + )
{
/* Check if the selected group is of this type */
for ( NumGrpThisType = 0 ;
NumGrpThisType < Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ;
NumGrpThisType + + )
2017-01-19 20:55:31 +01:00
if ( LstGrps - > GrpCods [ NumGrpSel ] = = Gbl . CurrentCrs . 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 ] ) ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_THE_USER_X_has_been_removed_from_the_group_of_type_Y_to_which_it_belonged ,
UsrDat - > FullName , Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ) ;
2017-05-11 23:45:46 +02:00
Ale_ShowAlert ( Ale_SUCCESS , Gbl . Alert . Txt ) ;
2014-12-01 23:55:08 +01:00
}
if ( ! AlreadyRegisteredInGrp ) // If the user does not belong to the selected group
{
2017-01-19 20:55:31 +01:00
Grp_AddUsrToGroup ( UsrDat , LstGrps - > GrpCods [ NumGrpSel ] ) ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_THE_USER_X_has_been_enroled_in_the_group_of_type_Y_Z ,
UsrDat - > FullName , Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . LstGrps [ NumGrpThisType ] . GrpName ) ;
2017-05-11 23:45:46 +02:00
Ale_ShowAlert ( Ale_SUCCESS , Gbl . Alert . Txt ) ;
2014-12-01 23:55:08 +01:00
}
break ; // Once we know the type of a selected group, it's not necessary to check the rest of types
}
}
/***** Free the list of groups of this type to which the user belonged *****/
Grp_FreeListCodGrp ( & LstGrpsHeBelongs ) ;
}
}
/*****************************************************************************/
/**************** Remove user of the groups indicados in a list **************/
/*****************************************************************************/
// Returns NumGrpsHeIsRemoved
unsigned Grp_RemoveUsrFromGroups ( struct UsrData * UsrDat , struct ListCodGrps * LstGrps )
{
extern const char * Txt_THE_USER_X_has_not_been_removed_from_any_group ;
extern const char * Txt_THE_USER_X_has_been_removed_from_one_group ;
extern const char * Txt_THE_USER_X_has_been_removed_from_Y_groups ;
struct ListCodGrps LstGrpsHeBelongs ;
2017-06-20 14:43:26 +02:00
unsigned NumGrpSel ;
unsigned NumGrpHeBelongs ;
unsigned NumGrpsHeIsRemoved = 0 ;
2014-12-01 23:55:08 +01:00
/***** Query in the database the group codes of any group the user belongs to *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , - 1L ,
UsrDat - > UsrCod , & LstGrpsHeBelongs ) ;
/***** For each group selected by me... *****/
for ( NumGrpSel = 0 ;
NumGrpSel < LstGrps - > NumGrps ;
NumGrpSel + + )
/* For each group to which the user belongs... */
for ( NumGrpHeBelongs = 0 ;
NumGrpHeBelongs < LstGrpsHeBelongs . NumGrps ;
NumGrpHeBelongs + + )
/* If the user belongs to a selected group from which he must be removed */
2017-01-19 20:55:31 +01:00
if ( LstGrpsHeBelongs . GrpCods [ NumGrpHeBelongs ] = = LstGrps - > GrpCods [ NumGrpSel ] )
2014-12-01 23:55:08 +01:00
{
2017-01-19 20:55:31 +01:00
Grp_RemoveUsrFromGroup ( UsrDat - > UsrCod , LstGrpsHeBelongs . GrpCods [ NumGrpHeBelongs ] ) ;
2014-12-01 23:55:08 +01:00
NumGrpsHeIsRemoved + + ;
}
/***** Write message to inform about how many groups the student has been removed from *****/
if ( NumGrpsHeIsRemoved = = 0 )
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
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 )
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_THE_USER_X_has_been_removed_from_one_group ,
UsrDat - > FullName ) ;
2014-12-01 23:55:08 +01:00
else // NumGrpsHeIsRemoved > 1
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_THE_USER_X_has_been_removed_from_Y_groups ,
UsrDat - > FullName , NumGrpsHeIsRemoved ) ;
2017-05-11 23:45:46 +02:00
Ale_ShowAlert ( Ale_SUCCESS , Gbl . Alert . Txt ) ;
2014-12-01 23:55:08 +01:00
/***** Free the list of groups of this type to which the user belonged *****/
Grp_FreeListCodGrp ( & LstGrpsHeBelongs ) ;
return NumGrpsHeIsRemoved ;
}
/*****************************************************************************/
/*************** Remove a user of all the groups of a course *****************/
/*****************************************************************************/
2017-06-20 14:43:26 +02:00
void Grp_RemUsrFromAllGrpsInCrs ( long UsrCod , long CrsCod )
2014-12-01 23:55:08 +01:00
{
2017-03-11 00:47:23 +01:00
char Query [ 512 ] ;
2018-10-10 23:56:42 +02:00
bool ItsMe = Usr_ItsMe ( UsrCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove user from all the groups of the course *****/
sprintf ( Query , " DELETE FROM crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE UsrCod=%ld AND GrpCod IN "
2014-12-01 23:55:08 +01:00
" (SELECT crs_grp.GrpCod FROM crs_grp_types,crs_grp "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod) " ,
2017-06-20 14:43:26 +02:00
UsrCod , CrsCod ) ;
2014-12-01 23:55:08 +01:00
DB_QueryDELETE ( Query , " can not remove a user from all groups of a course " ) ;
2017-06-20 14:43:26 +02:00
/***** Flush caches *****/
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ( ) ;
if ( ItsMe )
Grp_FlushCacheIBelongToGrp ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******* Remove a user from all the groups of all the user's courses *********/
/*****************************************************************************/
2017-06-20 14:43:26 +02:00
void Grp_RemUsrFromAllGrps ( long UsrCod )
2014-12-01 23:55:08 +01:00
{
2017-03-11 00:47:23 +01:00
char Query [ 128 ] ;
2018-10-10 23:56:42 +02:00
bool ItsMe = Usr_ItsMe ( UsrCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove user from all groups *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " DELETE FROM crs_grp_usr WHERE UsrCod=%ld " ,
2017-06-20 14:43:26 +02:00
UsrCod ) ;
2014-12-01 23:55:08 +01:00
DB_QueryDELETE ( Query , " can not remove a user from the groups he/she belongs to " ) ;
2017-06-20 14:43:26 +02:00
/***** Flush caches *****/
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ( ) ;
if ( ItsMe )
Grp_FlushCacheIBelongToGrp ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************* Remove a user from a group ************************/
/*****************************************************************************/
static void Grp_RemoveUsrFromGroup ( long UsrCod , long GrpCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 256 ] ;
2018-10-10 23:56:42 +02:00
bool ItsMe = Usr_ItsMe ( UsrCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove user from group *****/
sprintf ( Query , " DELETE FROM crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE GrpCod=%ld AND UsrCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpCod , UsrCod ) ;
DB_QueryDELETE ( Query , " can not remove a user from a group " ) ;
2017-06-20 14:43:26 +02:00
/***** Flush caches *****/
Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ( ) ;
if ( ItsMe )
Grp_FlushCacheIBelongToGrp ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Register a user in a group **************************/
/*****************************************************************************/
static void Grp_AddUsrToGroup ( struct UsrData * UsrDat , long GrpCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 256 ] ;
2014-12-01 23:55:08 +01:00
/***** Register in group *****/
2017-03-13 13:17:53 +01:00
sprintf ( Query , " INSERT INTO crs_grp_usr "
" (GrpCod,UsrCod) "
" VALUES "
2017-03-24 01:09:27 +01:00
" (%ld,%ld) " ,
2014-12-01 23:55:08 +01:00
GrpCod , UsrDat - > UsrCod ) ;
DB_QueryINSERT ( Query , " can not add a user to a group " ) ;
}
/*****************************************************************************/
/******************** List current group types for edition *******************/
/*****************************************************************************/
static void Grp_ListGroupTypesForEdition ( void )
{
2017-04-29 20:16:53 +02:00
2014-12-01 23:55:08 +01:00
extern const char * Txt_It_is_optional_to_choose_a_group ;
extern const char * Txt_It_is_mandatory_to_choose_a_group ;
extern const char * Txt_A_student_can_belong_to_several_groups ;
extern const char * Txt_A_student_can_only_belong_to_one_group ;
extern const char * Txt_The_groups_will_automatically_open ;
extern const char * Txt_The_groups_will_not_automatically_open ;
unsigned NumGrpTyp ;
2015-10-26 20:02:07 +01:00
unsigned UniqueId ;
char Id [ 32 ] ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
2017-06-11 20:09:59 +02:00
Tbl_StartTableWide ( 2 ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteHeadingGroupTypes ( ) ;
/***** List group types with forms for edition *****/
2015-10-26 20:02:07 +01:00
for ( NumGrpTyp = 0 , UniqueId = 1 ;
2014-12-01 23:55:08 +01:00
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
2015-10-26 20:02:07 +01:00
NumGrpTyp + + , UniqueId + + )
2014-12-01 23:55:08 +01:00
{
/* Put icon to remove group type */
fprintf ( Gbl . F . Out , " <tr> "
" <td class= \" BM \" > " ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( ActReqRemGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpTypCod ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2017-06-11 19:13:28 +02:00
Ico_PutIconRemove ( ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2015-03-13 00:16:02 +01:00
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Name of group type */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE \" > " ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( ActRenGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpTypCod ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2015-10-22 14:49:48 +02:00
fprintf ( Gbl . F . Out , " <input type= \" text \" name= \" GrpTypName \" "
2016-03-19 00:40:20 +01:00
" size= \" 12 \" maxlength= \" %u \" value= \" %s \" "
2015-10-22 14:49:48 +02:00
" onchange= \" document.getElementById('%s').submit(); \" /> " ,
2017-03-07 11:03:05 +01:00
Grp_MAX_CHARS_GROUP_TYPE_NAME ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ,
2016-01-14 10:31:09 +01:00
Gbl . Form . Id ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2015-03-13 00:16:02 +01:00
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Is it mandatory to register in any group? */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > " ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( ActChgMdtGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpTypCod ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2017-03-30 11:20:06 +02:00
fprintf ( Gbl . F . Out , " <select name= \" MandatoryEnrolment \" "
2015-09-28 18:28:29 +02:00
" style= \" width:150px; \" "
2015-10-22 14:49:48 +02:00
" onchange= \" document.getElementById('%s').submit(); \" > "
2014-12-01 23:55:08 +01:00
" <option value= \" N \" " ,
2016-01-14 10:31:09 +01:00
Gbl . Form . Id ) ;
2017-03-30 11:20:06 +02:00
if ( ! Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MandatoryEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
" <option value= \" Y \" " ,
Txt_It_is_optional_to_choose_a_group ) ;
2017-03-30 11:20:06 +02:00
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MandatoryEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
2015-03-13 00:16:02 +01:00
" </select> " ,
2014-12-01 23:55:08 +01:00
Txt_It_is_mandatory_to_choose_a_group ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2015-03-13 00:16:02 +01:00
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Is it possible to register in multiple groups? */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > " ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( ActChgMulGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpTypCod ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2017-03-30 11:20:06 +02:00
fprintf ( Gbl . F . Out , " <select name= \" MultipleEnrolment \" "
2015-09-28 18:28:29 +02:00
" style= \" width:150px; \" "
2015-10-22 14:49:48 +02:00
" onchange= \" document.getElementById('%s').submit(); \" > "
2014-12-01 23:55:08 +01:00
" <option value= \" N \" " ,
2016-01-14 10:31:09 +01:00
Gbl . Form . Id ) ;
2017-03-30 11:20:06 +02:00
if ( ! Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MultipleEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
" <option value= \" Y \" " ,
Txt_A_student_can_only_belong_to_one_group ) ;
2017-03-30 11:20:06 +02:00
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MultipleEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
2015-03-13 00:16:02 +01:00
" </select> " ,
2014-12-01 23:55:08 +01:00
Txt_A_student_can_belong_to_several_groups ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2015-03-13 00:16:02 +01:00
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Open time */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE \" > " ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( ActChgTimGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpTypCod ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2017-06-11 20:09:59 +02:00
Tbl_StartTableCenter ( 2 ) ;
2017-05-01 12:36:24 +02:00
fprintf ( Gbl . F . Out , " <tr> "
2015-09-28 18:28:29 +02:00
" <td class= \" LEFT_MIDDLE \" style= \" width:20px; \" > "
2015-07-22 11:18:11 +02:00
" <img src= \" %s/%s16x16.gif \" "
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> "
2014-12-01 23:55:08 +01:00
" </td> "
2015-08-03 20:22:41 +02:00
" <td class= \" LEFT_MIDDLE \" > " ,
2014-12-01 23:55:08 +01:00
Gbl . Prefs . IconsURL ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MustBeOpened ? " time " :
" time-off " ,
2015-07-22 11:18:11 +02:00
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MustBeOpened ? Txt_The_groups_will_automatically_open :
Txt_The_groups_will_not_automatically_open ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . MustBeOpened ? Txt_The_groups_will_automatically_open :
Txt_The_groups_will_not_automatically_open ) ;
2015-10-26 20:02:07 +01:00
sprintf ( Id , " open_time_%u " , UniqueId ) ;
Dat_WriteFormClientLocalDateTimeFromTimeUTC ( Id ,
" Open " ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . OpenTimeUTC ,
Gbl . Now . Date . Year ,
Gbl . Now . Date . Year + 1 ,
2016-12-03 20:08:01 +01:00
Dat_FORM_SECONDS_ON ,
2017-02-26 20:09:21 +01:00
Dat_HMS_DO_NOT_SET , // Don't set hour, minute and second
true ) ; // Submit on change
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " </td> "
2017-05-01 12:36:24 +02:00
" </tr> " ) ;
2017-06-11 20:09:59 +02:00
Tbl_EndTable ( ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2015-03-13 00:16:02 +01:00
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Number of groups of this type */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" %u "
" </td> "
2014-12-01 23:55:08 +01:00
" </tr> " ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) ;
}
2017-04-29 20:16:53 +02:00
/***** End table *****/
2017-06-11 20:09:59 +02:00
Tbl_EndTable ( ) ;
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 **************/
/*****************************************************************************/
static void Grp_PutIconsEditingGroupTypes ( void )
{
/***** Put icon to view groups *****/
Grp_PutIconToViewGroups ( ) ;
/***** Put icon to create a new type of group *****/
Grp_PutIconToCreateNewGroupType ( ) ;
}
static void Grp_PutIconToViewGroups ( void )
{
2017-06-11 19:13:28 +02:00
Ico_PutContextualIconToView ( ActReqSelGrp , NULL ) ;
2017-04-29 19:19:55 +02:00
}
static void Grp_PutIconToCreateNewGroupType ( void )
{
extern const char * Txt_New_type_of_group ;
/***** Put form to create a new type of group *****/
2017-05-25 13:43:54 +02:00
Lay_PutContextualLink ( ActReqEdiGrp , Grp_NEW_GROUP_TYPE_SECTION_ID , NULL ,
2017-04-29 19:19:55 +02:00
" plus64x64.png " ,
Txt_New_type_of_group , NULL ,
NULL ) ;
}
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 ;
extern const char * Txt_No_of_BR_groups ;
fprintf ( Gbl . F . Out , " <tr> "
" <th class= \" BM \" ></th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s<br />(%s) "
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2014-12-01 23:55:08 +01:00
" </tr> " ,
Txt_Type_of_group , Txt_eg_Lectures_Practicals ,
2017-03-30 11:20:06 +02:00
Txt_Mandatory_enrolment ,
Txt_Multiple_enrolment ,
2014-12-01 23:55:08 +01:00
Txt_Opening_of_groups ,
Txt_No_of_BR_groups ) ;
}
/*****************************************************************************/
/********************** List current groups for edition **********************/
/*****************************************************************************/
static void Grp_ListGroupsForEdition ( void )
{
extern const char * Txt_Group_X_open_click_to_close_it ;
extern const char * Txt_Group_X_closed_click_to_open_it ;
extern const char * Txt_File_zones_of_the_group_X_enabled_click_to_disable_them ;
extern const char * Txt_File_zones_of_the_group_X_disabled_click_to_enable_them ;
unsigned NumGrpTyp ;
unsigned NumTipGrpAux ;
unsigned NumGrpThisType ;
struct GroupType * GrpTyp ;
struct GroupType * GrpTypAux ;
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 *****/
2017-06-11 20:09:59 +02:00
Tbl_StartTableWide ( 2 ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteHeadingGroups ( ) ;
/***** List the groups *****/
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
GrpTyp = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
/* Write icon to remove group */
fprintf ( Gbl . F . Out , " <tr> "
" <td class= \" BM \" > " ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( ActReqRemGrp , Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2017-06-11 19:13:28 +02:00
Ico_PutIconRemove ( ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2015-03-13 00:16:02 +01:00
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Write icon to open/close group */
fprintf ( Gbl . F . Out , " <td class= \" BM \" > " ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( Grp - > Open ? ActCloGrp :
2017-04-29 01:12:35 +02:00
ActOpeGrp ,
2017-05-25 13:43:54 +02:00
Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
sprintf ( Gbl . Title ,
Grp - > Open ? Txt_Group_X_open_click_to_close_it :
Txt_Group_X_closed_click_to_open_it ,
Grp - > GrpName ) ;
2016-12-05 01:54:03 +01:00
fprintf ( Gbl . F . Out , " <input type= \" image \" src= \" %s/%s-on64x64.png \" "
2015-09-05 12:04:30 +02:00
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> " ,
2014-12-01 23:55:08 +01:00
Gbl . Prefs . IconsURL ,
2016-12-05 01:54:03 +01:00
Grp - > Open ? " unlock " :
" lock " ,
2014-12-01 23:55:08 +01:00
Gbl . Title ,
Gbl . Title ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2015-03-13 00:16:02 +01:00
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Write icon to activate file zones for this group */
fprintf ( Gbl . F . Out , " <td class= \" BM \" > " ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( Grp - > FileZones ? ActDisFilZonGrp :
2017-04-29 01:12:35 +02:00
ActEnaFilZonGrp ,
2017-05-25 13:43:54 +02:00
Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
sprintf ( Gbl . Title ,
Grp - > FileZones ? Txt_File_zones_of_the_group_X_enabled_click_to_disable_them :
Txt_File_zones_of_the_group_X_disabled_click_to_enable_them ,
Grp - > GrpName ) ;
fprintf ( Gbl . F . Out , " <input type= \" image \" src= \" %s/%s16x16.gif \" "
2015-09-05 12:04:30 +02:00
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> " ,
2014-12-01 23:55:08 +01:00
Gbl . Prefs . IconsURL ,
Grp - > FileZones ? " folder-yes " :
" folder-no " ,
Gbl . Title ,
Gbl . Title ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2015-03-13 00:16:02 +01:00
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Group type */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > " ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( ActChgGrpTyp , Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2017-03-11 00:47:23 +01:00
fprintf ( Gbl . F . Out , " <select name= \" GrpTypCod \" style= \" width:150px; \" "
2015-10-22 14:49:48 +02:00
" onchange= \" document.getElementById('%s').submit(); \" > " ,
2016-01-14 10:31:09 +01:00
Gbl . Form . Id ) ;
2014-12-01 23:55:08 +01:00
for ( NumTipGrpAux = 0 ;
NumTipGrpAux < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumTipGrpAux + + )
{
GrpTypAux = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumTipGrpAux ] ;
fprintf ( Gbl . F . Out , " <option value= \" %ld \" " , GrpTypAux - > GrpTypCod ) ;
if ( GrpTypAux - > GrpTypCod = = GrpTyp - > GrpTypCod )
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> " , GrpTypAux - > GrpTypName ) ;
}
2015-03-13 00:16:02 +01:00
fprintf ( Gbl . F . Out , " </select> " ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2015-03-13 00:16:02 +01:00
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Group name */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > " ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( ActRenGrp , Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2015-10-22 14:49:48 +02:00
fprintf ( Gbl . F . Out , " <input type= \" text \" name= \" GrpName \" "
" size= \" 40 \" maxlength= \" %u \" value= \" %s \" "
2015-11-09 20:22:41 +01:00
" onchange= \" document.getElementById('%s').submit(); \" /> " ,
2017-03-07 11:03:05 +01:00
Grp_MAX_CHARS_GROUP_NAME , Grp - > GrpName , Gbl . Form . Id ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2015-03-13 00:16:02 +01:00
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
2017-05-30 21:43:05 +02:00
/* Current number of users in this group */
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE \" > "
" %d "
" </td> " ,
Grp - > NumUsrs [ Role ] ) ;
2014-12-01 23:55:08 +01:00
/* Maximum number of students of the group (row[3]) */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > " ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( ActChgMaxStdGrp , Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpCod ( Grp - > GrpCod ) ;
2015-10-22 14:49:48 +02:00
fprintf ( Gbl . F . Out , " <input type= \" text \" name= \" MaxStudents \" "
" size= \" 3 \" maxlength= \" 10 \" value= \" " ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteMaxStdsGrp ( Grp - > MaxStudents ) ;
2015-10-22 14:49:48 +02:00
fprintf ( Gbl . F . Out , " \" onchange= \" document.getElementById('%s').submit(); \" /> " ,
2016-01-14 10:31:09 +01:00
Gbl . Form . Id ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2017-05-30 21:43:05 +02:00
fprintf ( Gbl . F . Out , " </td> "
" </tr> " ) ;
2014-12-01 23:55:08 +01:00
}
}
2016-11-14 10:05:41 +01:00
/***** End table *****/
2017-06-11 20:09:59 +02:00
Tbl_EndTable ( ) ;
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 ;
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
fprintf ( Gbl . F . Out , " <tr> "
" <th class= \" BM \" ></th> "
" <th class= \" BM \" ></th> "
" <th class= \" BM \" ></th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s<br />(%s) "
2017-05-30 21:43:05 +02:00
" </th> " ,
Txt_Type_BR_of_group ,
Txt_Group_name , Txt_eg_A_B ) ;
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
fprintf ( Gbl . F . Out , " <th class= \" CENTER_MIDDLE \" > "
" %s "
" </th> " ,
Txt_ROLES_PLURAL_BRIEF_Abc [ Role ] ) ;
fprintf ( Gbl . F . Out , " <th class= \" CENTER_MIDDLE \" > "
2014-12-26 22:11:03 +01:00
" %s "
" </th> "
2014-12-01 23:55:08 +01:00
" </tr> " ,
2017-05-30 21:43:05 +02:00
Txt_Max_BR_students ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-07-09 20:31:11 +02:00
/********* List groups of a type **********/
/********* to edit assignments, attendance events, surveys or games **********/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-09-19 14:20:49 +02:00
void Grp_ListGrpsToEditAsgAttSvyGam ( struct GroupType * GrpTyp , long Cod ,
Grp_AsgAttSvyGam_t Grp_AsgAttOrSvy )
2014-12-01 23:55:08 +01:00
{
struct ListCodGrps LstGrpsIBelong ;
unsigned NumGrpThisType ;
bool IBelongToThisGroup ;
struct Group * Grp ;
bool AssociatedToGrp = false ;
/***** Write heading *****/
Grp_WriteGrpHead ( GrpTyp ) ;
/***** Query from the database the groups of this type which I belong to *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , GrpTyp - > GrpTypCod ,
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
/***** List the groups *****/
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
/* Put checkbox to select the group */
fprintf ( Gbl . F . Out , " <tr> "
2015-09-04 19:26:08 +02:00
" <td class= \" LEFT_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( IBelongToThisGroup )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > "
2016-12-20 14:03:46 +01:00
" <input type= \" checkbox \" "
" id= \" Grp%ld \" name= \" GrpCods \" value= \" %ld \" " ,
Grp - > GrpCod ,
2014-12-01 23:55:08 +01:00
Grp - > GrpCod ) ;
if ( Cod > 0 ) // Cod == -1L means new assignment or survey
{
switch ( Grp_AsgAttOrSvy )
{
case Grp_ASSIGNMENT :
AssociatedToGrp = Asg_CheckIfAsgIsAssociatedToGrp ( Cod , Grp - > GrpCod ) ;
break ;
case Grp_ATT_EVENT :
AssociatedToGrp = Att_CheckIfAttEventIsAssociatedToGrp ( Cod , Grp - > GrpCod ) ;
break ;
case Grp_SURVEY :
AssociatedToGrp = Svy_CheckIfSvyIsAssociatedToGrp ( Cod , Grp - > GrpCod ) ;
break ;
2017-07-09 20:31:11 +02:00
case Grp_GAME :
2017-09-07 18:38:18 +02:00
AssociatedToGrp = Gam_CheckIfGamIsAssociatedToGrp ( Cod , Grp - > GrpCod ) ;
2017-07-09 20:31:11 +02:00
break ;
2014-12-01 23:55:08 +01:00
}
if ( AssociatedToGrp )
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
}
if ( ! ( IBelongToThisGroup | |
2017-06-04 18:18:54 +02:00
Gbl . Usrs . Me . Role . Logged = = Rol_SYS_ADM ) )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " disabled= \" disabled \" " ) ;
2016-12-20 14:03:46 +01:00
fprintf ( Gbl . F . Out , " onclick= \" uncheckParent(this,'WholeCrs') \" /> "
" </td> " ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteRowGrp ( Grp , IBelongToThisGroup ) ;
fprintf ( Gbl . F . Out , " </tr> " ) ;
}
/***** 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
2016-03-28 01:02:34 +02:00
if ( Gbl . CurrentCrs . Grps . NumGrps ) // This course has groups
{
/***** 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
2017-06-12 14:16:33 +02:00
/***** Start box *****/
2017-06-11 22:26:40 +02:00
Box_StartBox ( NULL , Txt_My_groups , ICanEdit ? Grp_PutIconToEditGroups :
NULL ,
2017-06-12 15:03:29 +02:00
Hlp_USERS_Groups , Box_NOT_CLOSABLE ) ;
2016-03-16 15:00:47 +01:00
2016-03-28 01:02:34 +02:00
if ( Gbl . CurrentCrs . Grps . NumGrps ) // This course has groups
2016-03-16 15:00:47 +01:00
{
2016-03-28 01:02:34 +02:00
/***** Start form *****/
if ( PutFormToChangeGrps )
2018-10-15 14:07:12 +02:00
Act_StartForm ( ActChgGrp ) ;
2016-03-28 01:02:34 +02:00
/***** List the groups the user belongs to for change *****/
2017-06-11 20:09:59 +02:00
Tbl_StartTableWide ( 2 ) ;
2016-03-28 01:02:34 +02:00
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) // If there are groups of this type
2017-05-30 11:35:01 +02:00
{
2017-06-04 18:18:54 +02:00
ICanChangeMyGrps | = Grp_ListGrpsForChangeMySelection ( & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ,
& NumGrpsThisTypeIBelong ) ;
2017-05-30 11:35:01 +02:00
NumGrpsIBelong + = NumGrpsThisTypeIBelong ;
}
2017-06-11 20:09:59 +02:00
Tbl_EndTable ( ) ;
2016-03-28 01:02:34 +02:00
/***** End form *****/
if ( PutFormToChangeGrps )
{
2017-06-04 18:18:54 +02:00
if ( ICanChangeMyGrps )
2017-06-11 19:02:40 +02:00
Btn_PutConfirmButton ( NumGrpsIBelong ? Txt_Change_my_groups :
2017-05-30 11:35:01 +02:00
Txt_Enrol_in_groups ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2016-03-28 01:02:34 +02:00
}
}
else // This course has no groups
{
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_No_groups_have_been_created_in_the_course_X ,
Gbl . CurrentCrs . Crs . FullName ) ;
2017-05-11 23:45:46 +02:00
Ale_ShowAlert ( Ale_INFO , Gbl . Alert . Txt ) ;
2017-03-01 17:06:24 +01:00
/***** Button to create group *****/
if ( ICanEdit )
{
2018-10-15 14:07:12 +02:00
Act_StartForm ( ActReqEdiGrp ) ;
2017-06-11 19:02:40 +02:00
Btn_PutConfirmButton ( Txt_Create_group ) ;
2018-10-15 14:07:12 +02:00
Act_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 *****/
2017-06-10 21:38:10 +02:00
Box_EndBox ( ) ;
2014-12-01 23:55:08 +01:00
2016-03-28 01:02:34 +02:00
if ( Gbl . CurrentCrs . Grps . NumGrps ) // This course has groups
/***** 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 *************************/
/*****************************************************************************/
2016-03-16 22:40:35 +01:00
static void Grp_PutIconToEditGroups ( void )
2016-03-16 15:00:47 +01:00
{
2017-06-11 19:13:28 +02:00
Ico_PutContextualIconToEdit ( ActReqEdiGrp , 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 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
GrpTyp = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
if ( GrpTyp - > NumGrps ) // If there are groups of this type
2017-06-20 01:58:16 +02:00
if ( Grp_GetFirstCodGrpIBelongTo ( GrpTyp - > GrpTypCod ) < 0 ) // If I don't belong to any group
if ( Grp_GetIfGrpIsAvailable ( GrpTyp - > GrpTypCod ) ) // If there is any group of this type available
2014-12-01 23:55:08 +01:00
{
2017-03-30 11:20:06 +02:00
if ( GrpTyp - > MandatoryEnrolment )
2014-12-01 23:55:08 +01:00
{
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
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 ) ;
2017-05-11 23:45:46 +02:00
Ale_ShowAlert ( Ale_WARNING , Gbl . Alert . Txt ) ;
2014-12-01 23:55:08 +01:00
}
else
{
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
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 ) ;
2017-05-11 23:45:46 +02:00
Ale_ShowAlert ( Ale_INFO , Gbl . Alert . Txt ) ;
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 ;
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 *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , GrpTyp - > GrpTypCod ,
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
2017-05-30 11:35:01 +02:00
* NumGrpsThisTypeIBelong = LstGrpsIBelong . NumGrps ;
2014-12-01 23:55:08 +01:00
2017-06-20 01:58:16 +02:00
/***** Check if I can change my selection *****/
switch ( Gbl . Usrs . Me . Role . Logged )
{
case Rol_STD :
if ( GrpTyp - > MultipleEnrolment ) // Enrolment is multiple
{
for ( NumGrpThisType = 0 , ICanChangeMySelectionForThisGrpTyp = false ;
NumGrpThisType < GrpTyp - > NumGrps & & ! ICanChangeMySelectionForThisGrpTyp ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
if ( Grp - > Open ) // If group is open
{
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
if ( IBelongToThisGroup ) // I belong to this group
ICanChangeMySelectionForThisGrpTyp = true ; // I can unregister from group
else // I don't belong
if ( Grp - > NumUsrs [ Rol_STD ] < Grp - > MaxStudents ) // Group is not full
ICanChangeMySelectionForThisGrpTyp = true ; // I can register into group
}
}
}
else // Enrolment is single
{
/* Step 1: Check if I belong to a closed group */
for ( NumGrpThisType = 0 , IBelongToAClosedGroup = false ;
NumGrpThisType < GrpTyp - > NumGrps & & ! IBelongToAClosedGroup ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
if ( ! Grp - > Open ) // If group is closed
{
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
if ( IBelongToThisGroup ) // I belong to this group
IBelongToAClosedGroup = true ; // I belong to a closed group
}
}
if ( IBelongToAClosedGroup ) // I belong to a closed group
ICanChangeMySelectionForThisGrpTyp = false ; // I can not unregister
else // I don't belong to a closed group
/* Step 2: Check if I can register in at least one group to which I don't belong */
for ( NumGrpThisType = 0 , ICanChangeMySelectionForThisGrpTyp = false ;
NumGrpThisType < GrpTyp - > NumGrps & & ! ICanChangeMySelectionForThisGrpTyp ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
if ( Grp - > Open & & // If group is open...
Grp - > NumUsrs [ Rol_STD ] < Grp - > MaxStudents ) // ...and not full
{
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
if ( ! IBelongToThisGroup ) // I don't belong to this group
ICanChangeMySelectionForThisGrpTyp = true ; // I can register into this group
}
}
}
break ;
case Rol_TCH :
case Rol_SYS_ADM :
ICanChangeMySelectionForThisGrpTyp = true ; // I can not register/unregister
break ;
default :
ICanChangeMySelectionForThisGrpTyp = false ; // I can not register/unregister
break ;
}
2014-12-01 23:55:08 +01:00
/***** List the groups *****/
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
2017-05-30 11:35:01 +02:00
/* Put radio item or checkbox to select the group */
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " <tr> "
2015-09-04 19:26:08 +02:00
" <td class= \" LEFT_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( IBelongToThisGroup )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > "
2014-12-22 23:18:56 +01:00
" <input type= \" " ) ;
2017-06-04 18:18:54 +02:00
if ( Gbl . Usrs . Me . Role . Logged = = Rol_STD & & // If I am a student
2017-05-30 11:35:01 +02:00
! GrpTyp - > MultipleEnrolment & & // ...and the enrolment is single
2017-06-20 01:58:16 +02:00
GrpTyp - > NumGrps > 1 ) // ...and there are more than one group
2014-12-01 23:55:08 +01:00
{
2017-05-30 11:35:01 +02:00
/* Put a radio item */
2016-12-20 14:03:46 +01:00
fprintf ( Gbl . F . Out , " radio \" id= \" Grp%ld \" name= \" GrpCod%ld \" "
" value= \" %ld \" " ,
Grp - > GrpCod , GrpTyp - > GrpTypCod ,
Grp - > GrpCod ) ;
2017-03-30 11:20:06 +02:00
if ( ! GrpTyp - > MandatoryEnrolment ) // If the enrolment is not mandatory, I can select no groups
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " onclick= \" selectUnselectRadio(this,this.form.GrpCod%ld,%u) \" " ,
GrpTyp - > GrpTypCod , GrpTyp - > NumGrps ) ;
}
2017-05-30 11:35:01 +02:00
else
/* Put a checkbox item */
2016-12-20 14:03:46 +01:00
fprintf ( Gbl . F . Out , " checkbox \" id= \" Grp%ld \" name= \" GrpCod%ld \" "
" value= \" %ld \" " ,
Grp - > GrpCod , GrpTyp - > GrpTypCod ,
Grp - > GrpCod ) ;
2014-12-01 23:55:08 +01:00
2017-06-20 01:58:16 +02:00
/* Group checked? */
2014-12-01 23:55:08 +01:00
if ( IBelongToThisGroup )
2017-05-30 11:35:01 +02:00
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ; // Group selected
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 ;
if ( ! ICanChangeMySelectionForThisGrp ) // I can not change my selection for this group
fprintf ( Gbl . F . Out , IBelongToThisGroup ? " readonly " : // I can not unregister (disabled does not work because the value is not submitted)
" disabled= \" disabled \" " ) ; // I can not register
2017-05-30 11:35:01 +02:00
fprintf ( Gbl . F . Out , " /> "
" </td> " ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteRowGrp ( Grp , IBelongToThisGroup ) ;
fprintf ( Gbl . F . Out , " </tr> " ) ;
}
/***** 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 ****************/
/*****************************************************************************/
// If UsrCod > 0 ==> mark her/his groups as checked
// 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 ) ;
2017-06-12 14:16:33 +02:00
/***** Start box and table *****/
2017-06-10 21:38:10 +02:00
Box_StartBoxTable ( NULL , Txt_Groups , NULL ,
2017-06-12 15:03:29 +02:00
Hlp_USERS_Groups , Box_NOT_CLOSABLE , 0 ) ;
2014-12-01 23:55:08 +01:00
/***** List to select the groups the user belongs to *****/
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps )
Grp_ListGrpsToAddOrRemUsrs ( & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] , UsrCod ) ;
2017-06-12 14:16:33 +02:00
/***** End table and box *****/
2017-06-10 21:38:10 +02:00
Box_EndBoxTable ( ) ;
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 ****************/
/*****************************************************************************/
// If UsrCod > 0 ==> mark her/his groups as checked
// If UsrCod <= 0 ==> do not mark any group as checked
static void Grp_ListGrpsToAddOrRemUsrs ( struct GroupType * GrpTyp , long UsrCod )
{
struct ListCodGrps LstGrpsIBelong ;
struct ListCodGrps LstGrpsUsrBelongs ;
unsigned NumGrpThisType ;
bool IBelongToThisGroup ;
bool UsrBelongsToThisGroup ;
struct Group * Grp ;
/***** Write heading *****/
Grp_WriteGrpHead ( GrpTyp ) ;
/***** Query from the database the groups of this type which I belong to *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , GrpTyp - > GrpTypCod ,
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
/***** Query from the database the groups of this type which I belong to *****/
if ( UsrCod > 0 )
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , GrpTyp - > GrpTypCod ,
Gbl . Usrs . Other . UsrDat . UsrCod , & LstGrpsUsrBelongs ) ;
/***** List the groups *****/
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
UsrBelongsToThisGroup = ( UsrCod > 0 ) ? Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsUsrBelongs ) :
false ;
/* Put checkbox to select the group */
fprintf ( Gbl . F . Out , " <tr> "
2015-09-04 19:26:08 +02:00
" <td class= \" LEFT_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( UsrBelongsToThisGroup )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > "
2016-12-20 14:03:46 +01:00
" <input type= \" checkbox \" "
" id= \" Grp%ld \" name= \" GrpCod%ld \" value= \" %ld \" " ,
Grp - > GrpCod , GrpTyp - > GrpTypCod ,
Grp - > GrpCod ) ;
2014-12-01 23:55:08 +01:00
if ( UsrBelongsToThisGroup )
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
if ( ! ( IBelongToThisGroup | |
2017-06-04 18:18:54 +02:00
Gbl . Usrs . Me . Role . Logged = = Rol_SYS_ADM ) )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " disabled= \" disabled \" " ) ;
fprintf ( Gbl . F . Out , " /></td> " ) ;
Grp_WriteRowGrp ( Grp , UsrBelongsToThisGroup ) ;
fprintf ( Gbl . F . Out , " </tr> " ) ;
}
/***** Free memory with the lists of groups *****/
if ( UsrCod > 0 )
Grp_FreeListCodGrp ( & LstGrpsUsrBelongs ) ;
Grp_FreeListCodGrp ( & LstGrpsIBelong ) ;
}
/*****************************************************************************/
/******* 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 ;
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 *****/
Grp_GetLstCodGrpsUsrBelongs ( Gbl . CurrentCrs . Crs . CrsCod , GrpTyp - > GrpTypCod ,
Gbl . Usrs . Me . UsrDat . UsrCod , & LstGrpsIBelong ) ;
2017-06-06 20:27:46 +02:00
/***** List the groups of this type *****/
2014-12-01 23:55:08 +01:00
for ( NumGrpThisType = 0 ;
NumGrpThisType < GrpTyp - > NumGrps ;
NumGrpThisType + + )
{
2017-06-06 20:27:46 +02:00
/* Pointer to group */
2014-12-01 23:55:08 +01:00
Grp = & ( GrpTyp - > LstGrps [ NumGrpThisType ] ) ;
2017-06-06 20:27:46 +02:00
/* Check if I belong to his group */
2014-12-01 23:55:08 +01:00
IBelongToThisGroup = Grp_CheckIfGrpIsInList ( Grp - > GrpCod , & LstGrpsIBelong ) ;
2017-06-06 20:27:46 +02:00
/* Check if I can select / unselect this group */
if ( IBelongToThisGroup )
ICanSelUnselGroup = true ;
else
switch ( Gbl . Usrs . Me . Role . Logged )
{
2017-07-02 18:53:35 +02:00
case Rol_STD :
2017-06-06 20:27:46 +02:00
case Rol_NET :
2017-07-02 18:53:35 +02:00
ICanSelUnselGroup = ( GroupsSelectableByStdsOrNETs = = Grp_ALL_GROUPS ) | |
2017-06-23 09:56:01 +02:00
IBelongToThisGroup ;
2017-06-06 20:27:46 +02:00
break ;
case Rol_TCH :
case Rol_DEG_ADM :
case Rol_CTR_ADM :
case Rol_INS_ADM :
case Rol_SYS_ADM :
2017-07-02 18:53:35 +02:00
ICanSelUnselGroup = true ; // GroupsSelectable is ignored
2017-06-06 20:27:46 +02:00
break ;
default :
2017-07-02 18:53:35 +02:00
ICanSelUnselGroup = false ; // GroupsSelectable is ignored
2017-06-06 20:27:46 +02:00
break ;
}
2014-12-01 23:55:08 +01:00
/* Put checkbox to select the group */
fprintf ( Gbl . F . Out , " <tr> "
2015-09-04 19:26:08 +02:00
" <td class= \" LEFT_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( IBelongToThisGroup )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > "
2016-12-20 14:03:46 +01:00
" <input type= \" checkbox \" "
" id= \" Grp%ld \" name= \" GrpCods \" value= \" %ld \" " ,
Grp - > GrpCod ,
2014-12-01 23:55:08 +01:00
Grp - > GrpCod ) ;
if ( Gbl . Usrs . ClassPhoto . AllGroups )
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
else
for ( NumGrpSel = 0 ;
NumGrpSel < Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps ;
NumGrpSel + + )
2017-01-19 20:55:31 +01:00
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods [ NumGrpSel ] = = Grp - > GrpCod )
2014-12-01 23:55:08 +01:00
{
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
break ;
}
2017-06-06 20:27:46 +02:00
if ( ICanSelUnselGroup )
fprintf ( Gbl . F . Out , " onclick= \" checkParent(this,'AllGroups') \" " ) ;
else
fprintf ( Gbl . F . Out , " disabled= \" disabled \" " ) ;
fprintf ( Gbl . F . Out , " /></td> " ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteRowGrp ( Grp , IBelongToThisGroup ) ;
fprintf ( Gbl . F . Out , " </tr> " ) ;
}
/***** 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 */
2017-06-06 20:27:46 +02:00
switch ( Gbl . Usrs . Me . Role . Logged )
{
case Rol_NET :
ICanSelUnselGroup = false ;
break ;
case Rol_STD :
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 ;
}
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " <tr> "
2015-08-03 20:22:41 +02:00
" <td class= \" LEFT_MIDDLE \" > "
2016-12-20 14:03:46 +01:00
" <input type= \" checkbox \" id= \" Grp%ld \" name= \" GrpCods \" "
" value= \" %ld \" " ,
- ( GrpTyp - > GrpTypCod ) ,
2014-12-01 23:55:08 +01:00
- ( GrpTyp - > GrpTypCod ) ) ;
2017-06-06 20:27:46 +02:00
if ( ICanSelUnselGroup )
{
if ( Gbl . Usrs . ClassPhoto . AllGroups )
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
else
for ( NumGrpSel = 0 ;
NumGrpSel < Gbl . CurrentCrs . Grps . LstGrpsSel . NumGrps ;
NumGrpSel + + )
if ( Gbl . CurrentCrs . Grps . LstGrpsSel . GrpCods [ NumGrpSel ] = = - ( GrpTyp - > GrpTypCod ) )
{
fprintf ( Gbl . F . Out , " checked= \" checked \" " ) ;
break ;
}
}
2014-12-01 23:55:08 +01:00
else
2017-06-06 20:27:46 +02:00
fprintf ( Gbl . F . Out , " disabled= \" disabled \" " ) ;
2016-12-20 14:03:46 +01:00
fprintf ( Gbl . F . Out , " onclick= \" checkParent(this,'AllGroups') \" /> "
" </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Column closed/open */
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" </td> " ) ;
2014-12-01 23:55:08 +01:00
/* Group name = students with no group */
2017-05-30 21:43:05 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT LEFT_MIDDLE \" > "
2016-12-20 14:03:46 +01:00
" <label for= \" Grp%ld \" >%s</label> "
2014-12-22 23:18:56 +01:00
" </td> " ,
2017-05-30 21:43:05 +02:00
- ( GrpTyp - > GrpTypCod ) , Txt_users_with_no_group ) ;
2014-12-01 23:55:08 +01:00
/* Number of students who don't belong to any group of this type */
2017-05-30 21:43:05 +02:00
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE \" > "
" %u "
" </td> " ,
Grp_CountNumUsrsInNoGrpsOfType ( Role , GrpTyp - > GrpTypCod ) ) ;
2014-12-01 23:55:08 +01:00
2017-05-30 21:43:05 +02:00
/* Last void columns for max. students and vacants */
2014-12-22 23:18:56 +01:00
fprintf ( Gbl . F . Out , " <td></td> "
2017-05-30 21:43:05 +02:00
" <td></td> "
" </tr> " ) ;
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 ;
2015-12-29 11:35:01 +01:00
extern const char * Txt_Today ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_Group ;
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 ;
2017-05-30 21:43:05 +02:00
Rol_Role_t Role ;
2014-12-01 23:55:08 +01:00
/***** Name of group type *****/
fprintf ( Gbl . F . Out , " <tr> "
2015-08-03 20:22:41 +02:00
" <td colspan= \" 6 \" class= \" GRP_TITLE LEFT_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" <br />%s " ,
2014-12-01 23:55:08 +01:00
GrpTyp - > GrpTypName ) ;
if ( GrpTyp - > MustBeOpened )
{
2015-10-26 20:02:07 +01:00
UniqueId + + ;
fprintf ( Gbl . F . Out , " <br />%s: "
" <span id= \" open_time_%u \" ></span> "
" <script type= \" text/javascript \" > "
2017-05-04 17:06:26 +02:00
" writeLocalDateHMSFromUTC('open_time_%u',%ld, "
2017-05-05 09:41:56 +02:00
" %u,', ','%s',true,true,0x7); "
2015-10-26 20:02:07 +01:00
" </script> " ,
Txt_Opening_of_groups ,
UniqueId ,
2017-05-04 17:06:26 +02:00
UniqueId , ( long ) GrpTyp - > OpenTimeUTC ,
( unsigned ) Gbl . Prefs . DateFormat , Txt_Today ) ;
2014-12-01 23:55:08 +01:00
}
fprintf ( Gbl . F . Out , " </td> "
" </tr> " ) ;
/***** Head row with title of each column *****/
fprintf ( Gbl . F . Out , " <tr> "
2015-09-05 19:19:39 +02:00
" <th colspan= \" 2 \" ></th> "
2015-09-06 20:02:14 +02:00
" <th class= \" LEFT_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" %s "
2017-05-30 21:43:05 +02:00
" </th> " ,
Txt_Group ) ;
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
fprintf ( Gbl . F . Out , " <th class= \" CENTER_MIDDLE \" > "
" %s "
" </th> " ,
Txt_ROLES_PLURAL_BRIEF_Abc [ Role ] ) ;
fprintf ( Gbl . F . Out , " <th class= \" CENTER_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" %s "
2015-09-05 19:19:39 +02:00
" </th> "
2015-09-06 20:02:14 +02:00
" <th class= \" CENTER_MIDDLE \" > "
2014-12-22 23:18:56 +01:00
" %s "
2015-09-05 19:19:39 +02:00
" </th> "
2014-12-01 23:55:08 +01:00
" </tr> " ,
Txt_Max_BR_students ,
Txt_Vacants ) ;
}
/*****************************************************************************/
/****************** Write a row with the data of a group *********************/
/*****************************************************************************/
static void Grp_WriteRowGrp ( struct Group * Grp , bool Highlight )
{
extern const char * Txt_Group_X_open ;
extern const char * Txt_Group_X_closed ;
int Vacant ;
2017-05-30 21:43:05 +02:00
Rol_Role_t Role ;
2014-12-01 23:55:08 +01:00
/***** Write icon to show if group is open or closed *****/
2015-07-22 11:18:11 +02:00
sprintf ( Gbl . Title , Grp - > Open ? Txt_Group_X_open :
Txt_Group_X_closed ,
Grp - > GrpName ) ;
2015-09-04 19:32:07 +02:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( Highlight )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
2015-09-28 18:28:29 +02:00
fprintf ( Gbl . F . Out , " \" style= \" width:15px; \" > "
2016-12-05 01:54:03 +01:00
" <img src= \" %s/%s-off64x64.png \" "
2015-07-22 11:18:11 +02:00
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> "
2015-07-22 11:18:11 +02:00
" </td> " ,
2014-12-01 23:55:08 +01:00
Gbl . Prefs . IconsURL ,
2016-12-05 01:54:03 +01:00
Grp - > Open ? " unlock " :
" lock " ,
2015-07-22 11:18:11 +02:00
Gbl . Title , Gbl . Title ) ;
2014-12-01 23:55:08 +01:00
/***** Group name *****/
2016-12-23 22:19:03 +01:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( Highlight )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > "
2016-12-23 22:19:03 +01:00
" <label for= \" Grp%ld \" class= \" DAT \" > "
2016-12-20 14:03:46 +01:00
" %s "
" </label> "
2014-12-22 23:18:56 +01:00
" </td> " ,
2016-12-20 14:03:46 +01:00
Grp - > GrpCod ,
2014-12-22 23:18:56 +01:00
Grp - > GrpName ) ;
2014-12-01 23:55:08 +01:00
2017-05-30 21:43:05 +02:00
/***** Current number of users in this group *****/
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
{
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE " ) ;
if ( Highlight )
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > "
" %d "
" </td> " ,
Grp - > NumUsrs [ Role ] ) ;
}
2014-12-01 23:55:08 +01:00
/***** Max. number of students in this group *****/
2015-09-04 19:32:07 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( Highlight )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > " ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteMaxStdsGrp ( Grp - > MaxStudents ) ;
2014-12-22 23:18:56 +01:00
fprintf ( Gbl . F . Out , " "
" </td> " ) ;
2014-12-01 23:55:08 +01:00
/***** Vacants in this group *****/
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE " ) ;
2014-12-01 23:55:08 +01:00
if ( Highlight )
2015-09-04 19:26:08 +02:00
fprintf ( Gbl . F . Out , " LIGHT_BLUE " ) ;
fprintf ( Gbl . F . Out , " \" > " ) ;
2017-05-30 21:43:05 +02:00
if ( Grp - > MaxStudents < = Grp_MAX_STUDENTS_IN_A_GROUP )
2014-12-01 23:55:08 +01:00
{
2017-05-30 21:43:05 +02:00
Vacant = ( int ) Grp - > MaxStudents - ( int ) Grp - > NumUsrs [ Rol_STD ] ;
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " %u " ,
Vacant > 0 ? ( unsigned ) Vacant :
0 ) ;
}
fprintf ( Gbl . F . Out , " </td> " ) ;
}
/*****************************************************************************/
/********************* 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 ;
/***** Start form *****/
2017-05-25 13:43:54 +02:00
Lay_StartSection ( Grp_NEW_GROUP_TYPE_SECTION_ID ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( ActNewGrpTyp , Grp_GROUP_TYPES_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** Start box *****/
2017-06-10 21:38:10 +02:00
Box_StartBoxTable ( NULL , Txt_New_type_of_group , NULL ,
2017-06-12 15:03:29 +02:00
NULL , Box_NOT_CLOSABLE , 2 ) ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
Grp_WriteHeadingGroupTypes ( ) ;
2017-04-29 20:16:53 +02:00
/***** Column to remove group type, disabled here *****/
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " <tr> "
2017-04-29 20:16:53 +02:00
" <td class= \" BM \" ></td> " ) ;
2014-12-01 23:55:08 +01:00
/***** Name of group type *****/
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE \" > "
2015-10-23 01:31:08 +02:00
" <input type= \" text \" name= \" GrpTypName \" "
2016-11-19 14:03:07 +01:00
" size= \" 12 \" maxlength= \" %u \" value= \" %s \" "
" required= \" required \" /> "
2014-12-01 23:55:08 +01:00
" </td> " ,
2017-03-07 11:03:05 +01:00
Grp_MAX_CHARS_GROUP_TYPE_NAME , Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
/***** Is it mandatory to register in any groups of this type? *****/
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > "
2017-03-30 11:20:06 +02:00
" <select name= \" MandatoryEnrolment \" "
2015-09-28 18:28:29 +02:00
" style= \" width:150px; \" > "
2014-12-01 23:55:08 +01:00
" <option value= \" N \" " ) ;
2017-03-30 11:20:06 +02:00
if ( ! Gbl . CurrentCrs . Grps . GrpTyp . MandatoryEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
" <option value= \" Y \" " ,
Txt_It_is_optional_to_choose_a_group ) ;
2017-03-30 11:20:06 +02:00
if ( Gbl . CurrentCrs . Grps . GrpTyp . MandatoryEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
" </select> "
" </td> " ,
Txt_It_is_mandatory_to_choose_a_group ) ;
/***** Is it possible to register in multiple groups of this type? *****/
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > "
2017-03-30 11:20:06 +02:00
" <select name= \" MultipleEnrolment \" "
2015-09-28 18:28:29 +02:00
" style= \" width:150px; \" > "
2014-12-01 23:55:08 +01:00
" <option value= \" N \" " ) ;
2017-03-30 11:20:06 +02:00
if ( ! Gbl . CurrentCrs . Grps . GrpTyp . MultipleEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
" <option value= \" Y \" " ,
Txt_A_student_can_only_belong_to_one_group ) ;
2017-03-30 11:20:06 +02:00
if ( Gbl . CurrentCrs . Grps . GrpTyp . MultipleEnrolment )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> "
" </select> "
" </td> " ,
Txt_A_student_can_belong_to_several_groups ) ;
/***** Open time *****/
2017-05-01 21:17:38 +02:00
fprintf ( Gbl . F . Out , " <td class= \" LEFT_MIDDLE \" > " ) ;
2017-06-11 20:09:59 +02:00
Tbl_StartTable ( 2 ) ;
2017-05-01 21:17:38 +02:00
fprintf ( Gbl . F . Out , " <tr> "
2015-10-26 20:02:07 +01:00
" <td class= \" LEFT_MIDDLE \" style= \" width:20px; \" > "
2015-07-22 11:18:11 +02:00
" <img src= \" %s/%s16x16.gif \" "
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> "
2014-12-01 23:55:08 +01:00
" </td> "
2015-10-26 20:02:07 +01:00
" <td class= \" LEFT_MIDDLE \" > " ,
2014-12-01 23:55:08 +01:00
Gbl . Prefs . IconsURL ,
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened ? " time " :
" time-off " ,
2015-07-22 11:18:11 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened ? Txt_The_groups_will_automatically_open :
Txt_The_groups_will_not_automatically_open ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened ? Txt_The_groups_will_automatically_open :
Txt_The_groups_will_not_automatically_open ) ;
2015-10-26 20:02:07 +01:00
Dat_WriteFormClientLocalDateTimeFromTimeUTC ( " open_time " ,
" Open " ,
Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC ,
Gbl . Now . Date . Year ,
Gbl . Now . Date . Year + 1 ,
2016-12-03 20:08:01 +01:00
Dat_FORM_SECONDS_ON ,
2017-02-26 20:09:21 +01:00
Dat_HMS_DO_NOT_SET , // Don't set hour, minute and second
false ) ; // Don't submit on change
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " </td> "
2017-05-01 21:17:38 +02:00
" </tr> " ) ;
2017-06-11 20:09:59 +02:00
Tbl_EndTable ( ) ;
2017-05-01 21:17:38 +02:00
fprintf ( Gbl . F . Out , " </td> " ) ;
2014-12-01 23:55:08 +01:00
/***** Number of groups of this type *****/
2017-04-29 20:16:53 +02:00
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE \" > "
" 0 " // It's a new group type ==> 0 groups
" </td> "
" </tr> " ) ;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** End table, send button and end box *****/
2017-06-11 19:02:40 +02:00
Box_EndBoxTableWithButton ( Btn_CREATE_BUTTON , Txt_Create_type_of_group ) ;
2014-12-01 23:55:08 +01:00
2015-04-11 23:46:21 +02:00
/***** End form *****/
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2017-05-25 13:43:54 +02:00
Lay_EndSection ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Put a form to create a new group ********************/
/*****************************************************************************/
static void Grp_PutFormToCreateGroup ( void )
{
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 ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_Create_group ;
unsigned NumGrpTyp ;
2017-05-30 21:43:05 +02:00
Rol_Role_t Role ;
2014-12-01 23:55:08 +01:00
/***** Start form *****/
2017-05-25 13:43:54 +02:00
Lay_StartSection ( Grp_NEW_GROUP_SECTION_ID ) ;
2018-10-15 14:07:12 +02:00
Act_StartFormAnchor ( ActNewGrp , Grp_GROUPS_SECTION_ID ) ;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** Start box and table *****/
2017-06-10 21:38:10 +02:00
Box_StartBoxTable ( NULL , Txt_New_group , NULL ,
2017-06-12 15:03:29 +02:00
NULL , Box_NOT_CLOSABLE , 2 ) ;
2014-12-01 23:55:08 +01:00
/***** Write heading *****/
Grp_WriteHeadingGroups ( ) ;
2017-04-29 20:16:53 +02:00
/***** Put disabled icons to open group and archive zone *****/
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " <tr> "
2017-04-29 20:16:53 +02:00
" <td class= \" BM \" ></td> "
2014-12-01 23:55:08 +01:00
" <td class= \" BM \" > "
2016-12-05 01:54:03 +01:00
" <img src= \" %s/lock-off64x64.png \" "
2015-07-22 11:18:11 +02:00
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> "
2014-12-01 23:55:08 +01:00
" </td> "
" <td class= \" BM \" > "
" <img src= \" %s/folder-no_off16x16.gif \" "
2015-07-22 11:18:11 +02:00
" alt= \" %s \" title= \" %s \" "
2016-11-14 10:05:41 +01:00
" class= \" ICO20x20 \" /> "
2014-12-01 23:55:08 +01:00
" </td> " ,
Gbl . Prefs . IconsURL ,
2015-07-22 19:20:30 +02:00
Txt_Group_closed ,
Txt_Group_closed ,
2014-12-01 23:55:08 +01:00
Gbl . Prefs . IconsURL ,
2015-07-22 19:20:30 +02:00
Txt_File_zones_disabled ,
Txt_File_zones_disabled ) ;
2014-12-01 23:55:08 +01:00
/***** Group type *****/
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > "
2017-03-11 00:47:23 +01:00
" <select name= \" GrpTypCod \" style= \" width:150px; \" > " ) ;
2014-12-01 23:55:08 +01:00
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
fprintf ( Gbl . F . Out , " <option value= \" %ld \" " ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod = = Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod )
fprintf ( Gbl . F . Out , " selected= \" selected \" " ) ;
fprintf ( Gbl . F . Out , " >%s</option> " ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypName ) ;
}
fprintf ( Gbl . F . Out , " </select> "
" </td> " ) ;
/***** Group name *****/
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > "
2015-10-23 01:31:08 +02:00
" <input type= \" text \" name= \" GrpName \" "
2016-11-19 14:03:07 +01:00
" size= \" 40 \" maxlength= \" %u \" value= \" %s \" "
" required= \" required \" /> "
" </td> " ,
2017-03-07 11:03:05 +01:00
Grp_MAX_CHARS_GROUP_NAME , Gbl . CurrentCrs . Grps . GrpName ) ;
2014-12-01 23:55:08 +01:00
2017-05-30 21:43:05 +02:00
/***** Current number of users in this group *****/
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
fprintf ( Gbl . F . Out , " <td class= \" DAT CENTER_MIDDLE \" > "
" 0 "
" </td> " ) ;
2014-12-01 23:55:08 +01:00
/***** Maximum number of students *****/
2015-08-03 20:22:41 +02:00
fprintf ( Gbl . F . Out , " <td class= \" CENTER_MIDDLE \" > "
2015-10-23 01:31:08 +02:00
" <input type= \" text \" name= \" MaxStudents \" "
" size= \" 3 \" maxlength= \" 10 \" value= \" " ) ;
2014-12-01 23:55:08 +01:00
Grp_WriteMaxStdsGrp ( Gbl . CurrentCrs . Grps . MaxStudents ) ;
2016-12-23 22:19:03 +01:00
fprintf ( Gbl . F . Out , " \" /> "
2017-05-30 21:43:05 +02:00
" </td> "
" </tr> " ) ;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** End table, send button and end box *****/
2017-06-11 19:02:40 +02:00
Box_EndBoxTableWithButton ( Btn_CREATE_BUTTON , Txt_Create_group ) ;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** End form *****/
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2017-05-25 13:43:54 +02:00
Lay_EndSection ( ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********** Create a list with current group types in this course ***********/
/*****************************************************************************/
void Grp_GetListGrpTypesInThisCrs ( Grp_WhichGroupTypes_t WhichGroupTypes )
{
char Query [ 1024 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned long NumRow ;
if ( + + Gbl . CurrentCrs . Grps . GrpTypes . NestedCalls > 1 ) // If list is created yet, there's nothing to do
return ;
/***** Open groups of this course that must be opened
if open time is in the past * * * * */
Grp_OpenGroupsAutomatically ( ) ;
/***** Get group types with groups + groups types without groups from database *****/
// The tables in the second part of the UNION requires ALIAS in order to LOCK TABLES when registering in groups
switch ( WhichGroupTypes )
{
case Grp_ONLY_GROUP_TYPES_WITH_GROUPS :
sprintf ( Query , " SELECT crs_grp_types.GrpTypCod,crs_grp_types.GrpTypName, "
" crs_grp_types.Mandatory,crs_grp_types.Multiple, "
" crs_grp_types.MustBeOpened, "
2015-10-26 20:02:07 +01:00
" UNIX_TIMESTAMP(crs_grp_types.OpenTime), "
2014-12-01 23:55:08 +01:00
" COUNT(crs_grp.GrpCod) "
" FROM crs_grp_types,crs_grp "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2014-12-01 23:55:08 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" GROUP BY crs_grp_types.GrpTypCod "
" ORDER BY crs_grp_types.GrpTypName " ,
Gbl . CurrentCrs . Crs . CrsCod ) ;
break ;
case Grp_ALL_GROUP_TYPES :
sprintf ( Query , " (SELECT crs_grp_types.GrpTypCod,crs_grp_types.GrpTypName AS GrpTypName, "
" crs_grp_types.Mandatory,crs_grp_types.Multiple, "
" crs_grp_types.MustBeOpened, "
2015-10-26 20:02:07 +01:00
" UNIX_TIMESTAMP(crs_grp_types.OpenTime), "
2014-12-01 23:55:08 +01:00
" COUNT(crs_grp.GrpCod) "
" FROM crs_grp_types,crs_grp "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2014-12-01 23:55:08 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" GROUP BY crs_grp_types.GrpTypCod) "
" UNION "
" (SELECT GrpTypCod,GrpTypName, "
" Mandatory,Multiple, "
2015-10-26 20:02:07 +01:00
" MustBeOpened, "
" UNIX_TIMESTAMP(OpenTime), "
2017-03-24 01:09:27 +01:00
" 0 "
" FROM crs_grp_types WHERE CrsCod=%ld "
2014-12-01 23:55:08 +01:00
" AND GrpTypCod NOT IN (SELECT GrpTypCod FROM crs_grp)) "
" ORDER BY GrpTypName " ,
Gbl . CurrentCrs . Crs . CrsCod ,
Gbl . CurrentCrs . Crs . CrsCod ) ;
break ;
}
Gbl . CurrentCrs . Grps . GrpTypes . Num = ( unsigned ) DB_QuerySELECT ( Query , & mysql_res , " can not get types of group of a course " ) ;
/***** Get group types *****/
Gbl . CurrentCrs . Grps . GrpTypes . NumGrpsTotal = 0 ;
if ( Gbl . CurrentCrs . Grps . GrpTypes . Num )
{
/***** Create a list of group types *****/
if ( ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes = ( struct GroupType * ) calloc ( Gbl . CurrentCrs . Grps . GrpTypes . Num , sizeof ( struct GroupType ) ) ) = = NULL )
Lay_ShowErrorAndExit ( " Not enough memory to store types of group. " ) ;
/***** Get group types *****/
for ( NumRow = 0 ;
NumRow < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumRow + + )
{
/* Get next group type */
row = mysql_fetch_row ( mysql_res ) ;
/* Get group type code (row[0]) */
if ( ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
Lay_ShowErrorAndExit ( " Wrong type of group. " ) ;
/* Get group type name (row[1]) */
2017-01-15 18:02:52 +01:00
Str_Copy ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . GrpTypName , row [ 1 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2014-12-01 23:55:08 +01:00
/* Is it mandatory to register in any groups of this type? (row[2]) */
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . 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]) */
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . MultipleEnrolment = ( row [ 3 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
/* Groups of this type must be opened? (row[4]) */
2016-09-07 18:48:10 +02:00
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . 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) */
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . OpenTimeUTC = Dat_GetUNIXTimeFromStr ( row [ 5 ] ) ;
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . MustBeOpened & = Grp_CheckIfOpenTimeInTheFuture ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
/* Number of groups of this type (row[6]) */
if ( sscanf ( row [ 6 ] , " %u " , & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . NumGrps ) ! = 1 )
Lay_ShowErrorAndExit ( " Wrong number of groups of a type. " ) ;
/* Add number of groups to total number of groups */
Gbl . CurrentCrs . Grps . GrpTypes . NumGrpsTotal + = Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . NumGrps ;
/* Initialize pointer to the list of groups of this type */
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumRow ] . LstGrps = NULL ;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/***************** Open automatically groups in this course ******************/
/*****************************************************************************/
void Grp_OpenGroupsAutomatically ( void )
{
char Query [ 512 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned NumGrpTypes ;
unsigned NumGrpTyp ;
long GrpTypCod ;
/***** Find group types to be opened *****/
sprintf ( Query , " SELECT GrpTypCod FROM crs_grp_types "
2017-03-24 01:09:27 +01:00
" WHERE CrsCod=%ld AND MustBeOpened='Y' "
2015-11-11 03:00:22 +01:00
" AND OpenTime<=NOW() " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Crs . CrsCod ) ;
NumGrpTypes = ( unsigned ) DB_QuerySELECT ( Query , & mysql_res ,
" can not get the types of group to be opened " ) ;
for ( NumGrpTyp = 0 ;
NumGrpTyp < NumGrpTypes ;
NumGrpTyp + + )
{
/* Get next group TYPE */
row = mysql_fetch_row ( mysql_res ) ;
if ( ( GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) > 0 )
{
/***** Open all the closed groups in this course the must be opened
and with open time in the past * * * */
sprintf ( Query , " UPDATE crs_grp SET Open='Y' "
2017-03-24 01:09:27 +01:00
" WHERE GrpTypCod=%ld AND Open='N' " ,
2014-12-01 23:55:08 +01:00
GrpTypCod ) ;
DB_QueryUPDATE ( Query , " can not open groups " ) ;
/***** To not try to open groups again, set MustBeOpened to false *****/
sprintf ( Query , " UPDATE crs_grp_types SET MustBeOpened='N' "
2017-03-24 01:09:27 +01:00
" WHERE GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpTypCod ) ;
DB_QueryUPDATE ( Query , " can not update the opening of a type of group " ) ;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/********* Create a list with group types and groups in this course **********/
/*****************************************************************************/
void Grp_GetListGrpTypesAndGrpsInThisCrs ( Grp_WhichGroupTypes_t WhichGroupTypes )
{
unsigned NumGrpTyp ;
unsigned NumGrp ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned long NumRows ;
struct GroupType * GrpTyp ;
struct Group * Grp ;
2017-05-30 21:43:05 +02:00
Rol_Role_t Role ;
2014-12-01 23:55:08 +01:00
/***** First we get the list of group types *****/
Grp_GetListGrpTypesInThisCrs ( WhichGroupTypes ) ;
/***** Then we get the list of groups for each group type *****/
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
GrpTyp = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
if ( GrpTyp - > NumGrps ) // If there are groups of this type...
{
/***** Query database *****/
if ( ( NumRows = Grp_GetGrpsOfType ( GrpTyp - > GrpTypCod , & mysql_res ) ) > 0 ) // Groups found...
{
// NumRows should be equal to GrpTyp->NumGrps
GrpTyp - > NumGrps = ( unsigned ) NumRows ;
/***** Create list with groups of this type *****/
if ( ( GrpTyp - > LstGrps = ( struct Group * ) calloc ( GrpTyp - > NumGrps , sizeof ( struct Group ) ) ) = = NULL )
Lay_ShowErrorAndExit ( " Not enough memory to store groups of a type. " ) ;
/***** Get the groups of this type *****/
for ( NumGrp = 0 ;
NumGrp < GrpTyp - > NumGrps ;
NumGrp + + )
{
Grp = & ( GrpTyp - > LstGrps [ NumGrp ] ) ;
/* Get next group */
row = mysql_fetch_row ( mysql_res ) ;
/* Get group code (row[0]) */
if ( ( Grp - > GrpCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
Lay_ShowErrorAndExit ( " Wrong code of group. " ) ;
/* Get group name (row[1]) */
2017-01-17 03:10:43 +01:00
Str_Copy ( Grp - > GrpName , row [ 1 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME ) ;
2014-12-01 23:55:08 +01:00
2017-05-30 21:43:05 +02:00
/* Get max number of students of group (row[2]) */
2014-12-01 23:55:08 +01:00
Grp - > MaxStudents = Grp_ConvertToNumMaxStdsGrp ( row [ 2 ] ) ;
2017-05-30 21:43:05 +02:00
/* Get number of current users in group */
for ( Role = Rol_TCH ;
Role > = Rol_STD ;
Role - - )
Grp - > NumUsrs [ Role ] = Grp_CountNumUsrsInGrp ( Role , Grp - > GrpCod ) ;
2014-12-01 23:55:08 +01:00
/* Get whether group is open ('Y') or closed ('N') (row[3]) */
2016-09-07 18:48:10 +02:00
Grp - > Open = ( row [ 3 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
/* Get whether group have file zones ('Y') or not ('N') (row[4]) */
2016-09-07 18:48:10 +02:00
Grp - > FileZones = ( row [ 4 ] [ 0 ] = = ' Y ' ) ;
2014-12-01 23:55:08 +01:00
}
}
else // Error: groups should be found, but really they haven't be found. This never should happen.
GrpTyp - > NumGrps = 0 ;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
}
}
/*****************************************************************************/
/********* Free list of groups types and list of groups of each type *********/
/*****************************************************************************/
void Grp_FreeListGrpTypesAndGrps ( void )
{
unsigned NumGrpTyp ;
struct GroupType * GrpTyp ;
if ( Gbl . CurrentCrs . Grps . GrpTypes . NestedCalls > 0 )
if ( - - Gbl . CurrentCrs . Grps . GrpTypes . NestedCalls = = 0 )
if ( Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes )
{
/***** Free memory used for each list of groups (one list for each group type) *****/
for ( NumGrpTyp = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
GrpTyp = & Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] ;
if ( GrpTyp - > LstGrps )
{
free ( ( void * ) GrpTyp - > LstGrps ) ;
GrpTyp - > LstGrps = NULL ;
GrpTyp - > NumGrps = 0 ;
}
}
/***** Free memory used by the list of group types *****/
free ( ( void * ) Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes ) ;
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes = NULL ;
Gbl . CurrentCrs . Grps . GrpTypes . Num = 0 ;
}
}
/*****************************************************************************/
/*********** Query the number of groups that hay in this course **************/
/*****************************************************************************/
unsigned Grp_CountNumGrpsInCurrentCrs ( void )
{
char Query [ 512 ] ;
/***** Get number of group in current course from database *****/
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp_types,crs_grp "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2014-12-01 23:55:08 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod " ,
Gbl . CurrentCrs . Crs . CrsCod ) ;
return ( unsigned ) DB_QueryCOUNT ( Query , " can not get number of groups in this course " ) ;
}
/*****************************************************************************/
/****************** Count number of groups in a group type *******************/
/*****************************************************************************/
static unsigned Grp_CountNumGrpsInThisCrsOfType ( long GrpTypCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 128 ] ;
2014-12-01 23:55:08 +01:00
/***** Get number of groups of a type from database *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp WHERE GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpTypCod ) ;
return ( unsigned ) DB_QueryCOUNT ( Query , " can not get number of groups of a type " ) ;
}
/*****************************************************************************/
/***************** Get current groups of a type in this course ***************/
/*****************************************************************************/
unsigned long Grp_GetGrpsOfType ( long GrpTypCod , MYSQL_RES * * mysql_res )
{
char Query [ 512 ] ;
/***** Get groups of a type from database *****/
sprintf ( Query , " SELECT GrpCod,GrpName,MaxStudents,Open,FileZones "
2015-01-27 20:50:44 +01:00
" FROM crs_grp "
2017-03-24 01:09:27 +01:00
" WHERE GrpTypCod=%ld "
2015-01-27 20:50:44 +01:00
" ORDER BY GrpName " ,
GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
return DB_QuerySELECT ( Query , mysql_res , " can not get groups of a type " ) ;
}
/*****************************************************************************/
/******************* 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 )
{
char Query [ 512 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned long NumRows ;
/***** Get data of a type of group from database *****/
2015-10-26 20:02:07 +01:00
sprintf ( Query , " SELECT GrpTypName,Mandatory,Multiple,MustBeOpened,UNIX_TIMESTAMP(OpenTime) "
2014-12-01 23:55:08 +01:00
" FROM crs_grp_types "
2017-03-24 01:09:27 +01:00
" WHERE CrsCod=%ld AND GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Crs . CrsCod , GrpTyp - > GrpTypCod ) ;
NumRows = DB_QuerySELECT ( Query , & mysql_res , " can not get type of group " ) ;
/***** Count number of rows in result *****/
if ( NumRows ! = 1 )
Lay_ShowErrorAndExit ( " Error when getting type of group. " ) ;
/***** Get some data of group type *****/
row = mysql_fetch_row ( mysql_res ) ;
2017-01-17 03:10:43 +01:00
Str_Copy ( GrpTyp - > GrpTypName , row [ 0 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2017-03-30 11:20:06 +02:00
GrpTyp - > MandatoryEnrolment = ( row [ 1 ] [ 0 ] = = ' Y ' ) ;
GrpTyp - > MultipleEnrolment = ( row [ 2 ] [ 0 ] = = ' Y ' ) ;
GrpTyp - > MustBeOpened = ( row [ 3 ] [ 0 ] = = ' Y ' ) ;
2015-10-26 20:02:07 +01:00
GrpTyp - > OpenTimeUTC = Dat_GetUNIXTimeFromStr ( row [ 4 ] ) ;
2014-12-01 23:55:08 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
2017-03-30 11:20:06 +02:00
/************* Check if a group type has multiple enrolment *****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-03-30 11:20:06 +02:00
static bool Grp_GetMultipleEnrolmentOfAGroupType ( long GrpTypCod )
2014-12-01 23:55:08 +01:00
{
2017-03-11 00:47:23 +01:00
char Query [ 128 ] ;
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 *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " SELECT Multiple FROM crs_grp_types WHERE GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpTypCod ) ;
2017-03-30 11:20:06 +02:00
if ( DB_QuerySELECT ( Query , & mysql_res , " can not get if type of group has multiple enrolment " ) ! = 1 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Error when getting type of group. " ) ;
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 )
{
char Query [ 512 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned long NumRows ;
2016-12-28 02:40:15 +01:00
/***** Reset values *****/
GrpDat - > GrpTypCod = - 1L ;
GrpDat - > CrsCod = - 1L ;
GrpDat - > GrpTypName [ 0 ] = ' \0 ' ;
GrpDat - > GrpName [ 0 ] = ' \0 ' ;
GrpDat - > MaxStudents = 0 ;
GrpDat - > Vacant = 0 ;
2017-03-30 11:20:06 +02:00
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 *****/
sprintf ( Query , " SELECT crs_grp_types.GrpTypCod,crs_grp_types.CrsCod, "
" crs_grp_types.GrpTypName,crs_grp_types.Multiple, "
" crs_grp.GrpName,crs_grp.MaxStudents, "
" crs_grp.Open,crs_grp.FileZones "
" FROM crs_grp,crs_grp_types "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp.GrpCod=%ld "
2016-12-28 02:40:15 +01:00
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod " ,
GrpDat - > GrpCod ) ;
NumRows = DB_QuerySELECT ( Query , & mysql_res , " can not get data of a group " ) ;
if ( NumRows = = 1 )
{
/***** Get data of group *****/
row = mysql_fetch_row ( mysql_res ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get the code of the group type (row[0]) */
if ( ( GrpDat - > GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < = 0 )
Lay_ShowErrorAndExit ( " Wrong code of type of group. " ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get the code of the course (row[1]) */
if ( ( GrpDat - > CrsCod = Str_ConvertStrCodToLongCod ( row [ 1 ] ) ) < = 0 )
Lay_ShowErrorAndExit ( " Wrong code of course. " ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get the name of the group type (row[2]) */
2017-01-17 03:10:43 +01:00
Str_Copy ( GrpDat - > GrpTypName , row [ 2 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get whether a student may be in one or multiple groups (row[3]) */
2017-03-30 11:20:06 +02:00
GrpDat - > MultipleEnrolment = ( row [ 3 ] [ 0 ] = = ' Y ' ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get the name of the group (row[4]) */
2017-01-17 03:10:43 +01:00
Str_Copy ( GrpDat - > GrpName , row [ 4 ] ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get maximum number of students (row[5]) */
GrpDat - > MaxStudents = Grp_ConvertToNumMaxStdsGrp ( row [ 5 ] ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get whether group is open or closed (row[6]) */
GrpDat - > Open = ( row [ 6 ] [ 0 ] = = ' Y ' ) ;
2015-01-24 19:30:44 +01:00
2016-12-28 02:40:15 +01:00
/* Get whether group has file zones (row[7]) */
GrpDat - > FileZones = ( row [ 7 ] [ 0 ] = = ' Y ' ) ;
}
2014-12-01 23:55:08 +01:00
2016-12-28 02:40:15 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************** Get the type of group of a group *********************/
/*****************************************************************************/
static long Grp_GetTypeOfGroupOfAGroup ( long GrpCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 128 ] ;
2014-12-01 23:55:08 +01:00
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
long GrpTypCod ;
/***** Get data of a group from database *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " SELECT GrpTypCod FROM crs_grp WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpCod ) ;
if ( DB_QuerySELECT ( Query , & mysql_res , " can not get the type of a group " ) ! = 1 )
Lay_ShowErrorAndExit ( " Error when getting group. " ) ;
/***** Get data of group *****/
row = mysql_fetch_row ( mysql_res ) ;
/* Get the code of the group type (row[0]) */
if ( ( GrpTypCod = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
Lay_ShowErrorAndExit ( " Wrong code of type of group. " ) ;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
return GrpTypCod ;
}
/*****************************************************************************/
/******************** Check if a group exists in database ********************/
/*****************************************************************************/
bool Grp_CheckIfGroupExists ( long GrpCod )
{
char Query [ 128 ] ;
/***** Get if a group exists from database *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp WHERE GrpCod=%ld " , GrpCod ) ;
2014-12-01 23:55:08 +01:00
return ( DB_QueryCOUNT ( Query , " can not check if a group exists " ) ! = 0 ) ;
}
/*****************************************************************************/
/******************* Check if a group belongs to a course ********************/
/*****************************************************************************/
bool Grp_CheckIfGroupBelongsToCourse ( long GrpCod , long CrsCod )
{
2016-04-12 22:28:15 +02:00
char Query [ 256 ] ;
2014-12-01 23:55:08 +01:00
/***** Get if a group exists from database *****/
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp,crs_grp_types "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp.GrpCod=%ld "
2014-12-01 23:55:08 +01:00
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_types.CrsCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpCod , CrsCod ) ;
return ( DB_QueryCOUNT ( Query , " can not check if a group belongs to a course " ) ! = 0 ) ;
}
/*****************************************************************************/
2017-05-30 21:43:05 +02:00
/********************* Count number of users in a group **********************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-05-30 21:43:05 +02:00
unsigned Grp_CountNumUsrsInGrp ( Rol_Role_t Role , long GrpCod )
2014-12-01 23:55:08 +01:00
{
char Query [ 512 ] ;
/***** Get number of students in a group from database *****/
sprintf ( Query , " SELECT COUNT(*) "
" FROM crs_grp_usr,crs_grp,crs_grp_types,crs_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_usr.GrpCod=%ld "
2014-12-01 23:55:08 +01:00
" AND crs_grp_usr.GrpCod=crs_grp.GrpCod "
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod "
" AND crs_grp_types.CrsCod=crs_usr.CrsCod "
" AND crs_grp_usr.UsrCod=crs_usr.UsrCod "
2017-03-24 01:09:27 +01:00
" AND crs_usr.Role=%u " ,
2017-05-30 21:43:05 +02:00
GrpCod , ( unsigned ) Role ) ;
2014-12-01 23:55:08 +01:00
return ( unsigned ) DB_QueryCOUNT ( Query ,
2017-05-30 21:43:05 +02:00
" can not get number of users in a group " ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-05-30 21:43:05 +02:00
/*** Count # of users of current course not belonging to groups of a type ****/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-05-30 21:43:05 +02:00
static unsigned Grp_CountNumUsrsInNoGrpsOfType ( Rol_Role_t Role , long GrpTypCod )
2014-12-01 23:55:08 +01:00
{
char Query [ 512 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
2017-05-30 21:43:05 +02:00
unsigned NumUsrs ;
2014-12-01 23:55:08 +01:00
2017-05-30 21:43:05 +02:00
/***** Get number of users not belonging to groups of a type ******/
2014-12-01 23:55:08 +01:00
sprintf ( Query , " SELECT COUNT(UsrCod) FROM crs_usr "
2017-03-24 01:09:27 +01:00
" WHERE CrsCod=%ld AND Role=%u "
2017-03-11 00:47:23 +01:00
" AND UsrCod NOT IN "
" (SELECT DISTINCT crs_grp_usr.UsrCod "
" FROM crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp.GrpTypCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod) " ,
2017-05-30 21:43:05 +02:00
Gbl . CurrentCrs . Crs . CrsCod , ( unsigned ) Role , GrpTypCod ) ;
DB_QuerySELECT ( Query , & mysql_res , " can not get the number of users "
" not belonging to groups of a type " ) ;
2014-12-01 23:55:08 +01:00
2017-05-30 21:43:05 +02:00
/***** Get the number of users (row[0]) *****/
2014-12-01 23:55:08 +01:00
row = mysql_fetch_row ( mysql_res ) ;
2017-05-30 21:43:05 +02:00
if ( sscanf ( row [ 0 ] , " %u " , & NumUsrs ) ! = 1 )
Lay_ShowErrorAndExit ( " Error when getting the number of users "
" not belonging to groups of a type. " ) ;
2014-12-01 23:55:08 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
2017-05-30 21:43:05 +02:00
return NumUsrs ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/**** Get the first code of group of cierto type al that pert. a student *****/
/*****************************************************************************/
2017-06-20 01:58:16 +02:00
// Return -GrpTypCod if I don't belong to any group of type GrpTypCod
2014-12-01 23:55:08 +01:00
2017-06-20 01:58:16 +02:00
static long Grp_GetFirstCodGrpIBelongTo ( long GrpTypCod )
2014-12-01 23:55:08 +01:00
{
2017-03-11 00:47:23 +01:00
char Query [ 512 ] ;
2014-12-01 23:55:08 +01:00
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned long NumRows ;
long CodGrpIBelong ;
2017-06-20 01:58:16 +02:00
/***** Get a group which I belong to from database *****/
2017-03-11 00:47:23 +01:00
sprintf ( Query , " SELECT crs_grp.GrpCod FROM crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp.GrpTypCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_usr.UsrCod=%ld " ,
2017-06-20 01:58:16 +02:00
GrpTypCod , Gbl . Usrs . Me . UsrDat . UsrCod ) ;
NumRows = DB_QuerySELECT ( Query , & mysql_res , " can not check if you belong to a group " ) ;
2014-12-01 23:55:08 +01:00
/***** Get the group *****/
if ( NumRows = = 0 )
CodGrpIBelong = - GrpTypCod ;
else // If there are more than a group, only get the first one
{
row = mysql_fetch_row ( mysql_res ) ;
/* Get the code of group (row[0]) */
if ( ( CodGrpIBelong = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
Lay_ShowErrorAndExit ( " Wrong code of group. " ) ;
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
return CodGrpIBelong ;
}
/*****************************************************************************/
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 )
{
char Query [ 256 ] ;
2017-05-31 01:31:27 +02:00
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 *****/
2014-12-01 23:55:08 +01:00
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE GrpCod=%ld AND UsrCod=%ld " ,
2014-12-01 23:55:08 +01:00
GrpCod , Gbl . Usrs . Me . UsrDat . UsrCod ) ;
2017-06-20 14:43:26 +02:00
Gbl . Cache . IBelongToGrp . GrpCod = GrpCod ;
2017-06-23 15:12:49 +02:00
Gbl . Cache . IBelongToGrp . IBelong = ( DB_QueryCOUNT ( Query , " can not check "
" if you belong to a group " ) ! = 0 ) ;
2017-06-20 14:43:26 +02:00
return Gbl . Cache . IBelongToGrp . IBelong ;
}
/*****************************************************************************/
/*************** Check if a user belongs to any of my courses ****************/
/*****************************************************************************/
void Grp_FlushCacheUsrSharesAnyOfMyGrpsInCurrentCrs ( void )
{
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . UsrCod = - 1L ;
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares = false ;
}
bool Grp_CheckIfUsrSharesAnyOfMyGrpsInCurrentCrs ( const struct UsrData * UsrDat )
{
char Query [ 512 ] ;
2018-10-10 14:03:06 +02:00
bool ItsMe ;
2017-06-20 14:43:26 +02:00
/***** 1. Fast check: Am I logged? *****/
if ( ! Gbl . Usrs . Me . Logged )
return false ;
/***** 2. Fast check: Is it a valid user code? *****/
if ( UsrDat - > UsrCod < = 0 )
return false ;
/***** 3. Fast check: Is it a course selected? *****/
if ( Gbl . CurrentCrs . Crs . CrsCod < = 0 )
return false ;
/***** 4. Fast check: Do I belong to the current course? *****/
if ( ! Gbl . Usrs . Me . IBelongToCurrentCrs )
return false ;
/***** 5. Fast check: It's me? *****/
2018-10-10 23:56:42 +02:00
ItsMe = Usr_ItsMe ( UsrDat - > UsrCod ) ;
2018-10-10 14:03:06 +02:00
if ( ItsMe )
2017-06-20 14:43:26 +02:00
return true ;
/***** 6. Fast check: Is already calculated if user shares
any group in the current course with me ? * * * * */
if ( UsrDat - > UsrCod = = Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . UsrCod )
return Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares ;
/***** 7. Fast / slow check: Does he/she belong to the current course? *****/
if ( ! Usr_CheckIfUsrBelongsToCurrentCrs ( UsrDat ) )
{
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . UsrCod = UsrDat - > UsrCod ;
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares = false ;
return false ;
}
2017-06-23 15:12:49 +02:00
/***** 8. Fast check: Course has groups? *****/
if ( ! Gbl . CurrentCrs . Grps . NumGrps )
{
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 ;
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp_usr "
" WHERE UsrCod=%ld "
" AND GrpCod IN "
" (SELECT crs_grp_usr.GrpCod "
" FROM crs_grp_usr,crs_grp,crs_grp_types "
" WHERE crs_grp_usr.UsrCod=%ld "
" AND crs_grp_usr.GrpCod=crs_grp.GrpCod "
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod "
" AND crs_grp_types.CrsCod=%ld) " ,
UsrDat - > UsrCod ,
Gbl . Usrs . Me . UsrDat . UsrCod ,
Gbl . CurrentCrs . Crs . CrsCod ) ;
2017-06-23 15:12:49 +02:00
Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares = ( DB_QueryCOUNT ( Query , " can not check "
" if a user shares any group "
" in the current course with you " ) ! = 0 ) ;
2017-06-20 14:43:26 +02:00
return Gbl . Cache . UsrSharesAnyOfMyGrpsInCurrentCrs . Shares ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-03-30 11:20:06 +02:00
/**** Get the number of types of group with mandatory enrolment *****/
2014-12-01 23:55:08 +01:00
/**** that have any group open and with any vacant *****/
/**** and I don't belong to any of these groups as student *****/
/*****************************************************************************/
2017-05-30 21:43:05 +02:00
unsigned Grp_NumGrpTypesMandatIDontBelongAsStd ( void )
2014-12-01 23:55:08 +01:00
{
char Query [ 4096 ] ;
unsigned NumGrpTypes ;
2017-05-30 21:43:05 +02:00
/***** Get the number of types of groups with mandatory enrolment
which I don ' t belong to as student , from database * * * * */
2014-12-01 23:55:08 +01:00
sprintf ( Query , " SELECT COUNT(DISTINCT GrpTypCod) FROM "
2017-03-11 00:47:23 +01:00
" (SELECT crs_grp_types.GrpTypCod AS GrpTypCod, "
" COUNT(*) AS NumStudents, "
" crs_grp.MaxStudents as MaxStudents "
2014-12-01 23:55:08 +01:00
" FROM crs_grp_types,crs_grp,crs_grp_usr,crs_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp_types.Mandatory='Y' "
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.Open='Y' "
2014-12-01 23:55:08 +01:00
" AND crs_grp_types.CrsCod=crs_usr.CrsCod "
2017-03-11 00:47:23 +01:00
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
" AND crs_grp_usr.UsrCod=crs_usr.UsrCod "
2017-03-24 01:09:27 +01:00
" AND crs_usr.Role=%u "
2017-03-11 00:47:23 +01:00
" GROUP BY crs_grp.GrpCod "
" HAVING NumStudents<MaxStudents) AS grp_types_open_not_full "
2014-12-01 23:55:08 +01:00
" WHERE GrpTypCod NOT IN "
2017-03-11 00:47:23 +01:00
" (SELECT DISTINCT crs_grp_types.GrpTypCod "
" FROM crs_grp_types,crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp_types.Mandatory='Y' "
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_usr.UsrCod=%ld) " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Crs . CrsCod ,
2017-05-18 19:13:41 +02:00
( unsigned ) Rol_STD ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Crs . CrsCod ,
Gbl . Usrs . Me . UsrDat . UsrCod ) ;
2017-05-30 21:43:05 +02:00
NumGrpTypes = DB_QueryCOUNT ( Query , " can not get the number of types of group "
" of mandatory registration "
" to which you don't belong to " ) ;
2014-12-01 23:55:08 +01:00
return NumGrpTypes ;
}
/*****************************************************************************/
/********** Query if any group of a type is open and has vacants *************/
/*****************************************************************************/
static bool Grp_GetIfGrpIsAvailable ( long GrpTypCod )
{
char Query [ 2048 ] ;
unsigned NumGrpTypes ;
/***** Get the number of types of group (0 or 1) of a type
with one or more open groups with vacants , from database * * * * */
2017-06-20 01:58:16 +02:00
sprintf ( Query , " SELECT COUNT(GrpTypCod) FROM "
" ( "
// Groups with students
" SELECT crs_grp_types.GrpTypCod AS GrpTypCod, "
2017-03-11 00:47:23 +01:00
" COUNT(*) AS NumStudents, "
" crs_grp.MaxStudents as MaxStudents "
2014-12-01 23:55:08 +01:00
" FROM crs_grp_types,crs_grp,crs_grp_usr,crs_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.GrpTypCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.Open='Y' "
" AND crs_grp_types.CrsCod=crs_usr.CrsCod "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
" AND crs_grp_usr.UsrCod=crs_usr.UsrCod "
2017-03-24 01:09:27 +01:00
" AND crs_usr.Role=%u "
2017-03-11 00:47:23 +01:00
" GROUP BY crs_grp.GrpCod "
2017-06-20 01:58:16 +02:00
" HAVING NumStudents<MaxStudents "
" UNION "
// Groups without students
" SELECT crs_grp_types.GrpTypCod AS GrpTypCod, "
" 0 AS NumStudents, "
" crs_grp.MaxStudents as MaxStudents "
" FROM crs_grp_types,crs_grp "
" WHERE crs_grp_types.GrpTypCod=%ld "
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.Open='Y' "
" AND crs_grp.MaxStudents > 0 "
" AND crs_grp.GrpCod NOT IN "
" (SELECT crs_grp_usr.GrpCod "
" FROM crs_grp_types,crs_usr,crs_grp_usr "
" WHERE crs_grp_types.GrpTypCod=%ld "
" AND crs_grp_types.CrsCod=crs_usr.CrsCod "
" AND crs_usr.Role=%u "
" AND crs_usr.UsrCod=crs_grp_usr.UsrCod) "
" ) AS available_grp_types " ,
GrpTypCod , ( unsigned ) Rol_STD ,
GrpTypCod ,
2017-05-18 19:13:41 +02:00
GrpTypCod , ( unsigned ) Rol_STD ) ;
2014-12-01 23:55:08 +01:00
NumGrpTypes = DB_QueryCOUNT ( Query , " can not check if a type of group has available groups " ) ;
return ( NumGrpTypes ! = 0 ) ;
}
/*****************************************************************************/
/****** Query list of group codes of a type to which a user belongs to *******/
/*****************************************************************************/
// If CrsCod < 0 ==> get the groups from all the user's courses
// If GrpTypCod < 0 ==> get the groups of any type
static void Grp_GetLstCodGrpsUsrBelongs ( long CrsCod , long GrpTypCod ,
long UsrCod , struct ListCodGrps * LstGrps )
{
char Query [ 1024 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned NumGrp ;
/***** Get groups which a user belong to from database *****/
if ( CrsCod < 0 ) // Query the groups from all the user's courses
2017-03-11 00:47:23 +01:00
sprintf ( Query , " SELECT GrpCod "
" FROM crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE UsrCod=%ld " , // Groups will be unordered
2015-01-27 20:50:44 +01:00
UsrCod ) ;
2014-12-01 23:55:08 +01:00
else if ( GrpTypCod < 0 ) // Query the groups of any type in the course
2017-03-11 00:47:23 +01:00
sprintf ( Query , " SELECT crs_grp.GrpCod "
" FROM crs_grp_types,crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_usr.UsrCod=%ld "
2014-12-01 23:55:08 +01:00
" ORDER BY crs_grp_types.GrpTypName,crs_grp.GrpName " ,
Gbl . CurrentCrs . Crs . CrsCod , UsrCod ) ;
else // Query only the groups of specified type in the course
2017-03-11 00:47:23 +01:00
sprintf ( Query , " SELECT crs_grp.GrpCod "
" FROM crs_grp_types,crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
" AND crs_grp_types.GrpTypCod=%ld "
2017-03-11 00:47:23 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_usr.UsrCod=%ld "
2014-12-01 23:55:08 +01:00
" ORDER BY crs_grp.GrpName " ,
Gbl . CurrentCrs . Crs . CrsCod , GrpTypCod , UsrCod ) ;
LstGrps - > NumGrps = ( unsigned ) DB_QuerySELECT ( Query , & mysql_res , " can not get the groups which a user belongs to " ) ;
/***** Get the groups *****/
if ( LstGrps - > NumGrps )
{
/***** Create a list of groups the user belongs to *****/
2017-01-19 20:55:31 +01:00
if ( ( LstGrps - > GrpCods = ( long * ) calloc ( LstGrps - > NumGrps , sizeof ( long ) ) ) = = NULL )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Not enough memory to store codes of groups a user belongs to. " ) ;
for ( NumGrp = 0 ;
NumGrp < LstGrps - > NumGrps ;
NumGrp + + )
{
row = mysql_fetch_row ( mysql_res ) ;
/* Get the code of group (row[0]) */
2017-01-19 20:55:31 +01:00
if ( ( LstGrps - > GrpCods [ NumGrp ] = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Wrong code of group. " ) ;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/********** Query list of group codes with file zones I belong to ************/
/*****************************************************************************/
void Grp_GetLstCodGrpsWithFileZonesIBelong ( struct ListCodGrps * LstGrps )
{
char Query [ 1024 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
unsigned NumGrp ;
/***** Get groups which I belong to from database *****/
2017-03-11 00:47:23 +01:00
sprintf ( Query , " SELECT crs_grp.GrpCod "
" FROM crs_grp_types,crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp_types.CrsCod=%ld "
2015-10-26 20:02:07 +01:00
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod "
2014-12-01 23:55:08 +01:00
" AND crs_grp.FileZones='Y' "
2015-10-26 20:02:07 +01:00
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_usr.UsrCod=%ld "
2014-12-01 23:55:08 +01:00
" ORDER BY crs_grp_types.GrpTypName,crs_grp.GrpName " ,
Gbl . CurrentCrs . Crs . CrsCod , Gbl . Usrs . Me . UsrDat . UsrCod ) ;
LstGrps - > NumGrps = ( unsigned ) DB_QuerySELECT ( Query , & mysql_res , " can not get the groups which I belong to " ) ;
/***** Get the groups *****/
if ( LstGrps - > NumGrps )
{
/***** Create a list of groups I belong to *****/
2017-01-19 20:55:31 +01:00
if ( ( LstGrps - > GrpCods = ( long * ) calloc ( LstGrps - > NumGrps , sizeof ( long ) ) ) = = NULL )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Not enough memory to store codes of groups I belongs to. " ) ;
for ( NumGrp = 0 ;
NumGrp < LstGrps - > NumGrps ;
NumGrp + + )
{
row = mysql_fetch_row ( mysql_res ) ;
/* Get the code of group (row[0]) */
2017-01-19 20:55:31 +01:00
if ( ( LstGrps - > GrpCods [ NumGrp ] = Str_ConvertStrCodToLongCod ( row [ 0 ] ) ) < 0 )
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ( " Wrong code of group. " ) ;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/******** Check if a group is in a list of groups which I belong to **********/
/*****************************************************************************/
static bool Grp_CheckIfGrpIsInList ( long GrpCod , struct ListCodGrps * LstGrps )
{
unsigned NumGrp ;
for ( NumGrp = 0 ;
NumGrp < LstGrps - > NumGrps ;
NumGrp + + )
2017-01-19 20:55:31 +01:00
if ( GrpCod = = LstGrps - > GrpCods [ NumGrp ] )
2014-12-01 23:55:08 +01:00
return true ;
return false ;
}
/*****************************************************************************/
/********** Query names of groups of a type which user belongs to ************/
/*****************************************************************************/
void Grp_GetNamesGrpsStdBelongsTo ( long GrpTypCod , long UsrCod , char * GroupNames )
{
char Query [ 512 ] ;
MYSQL_RES * mysql_res ;
MYSQL_ROW row ;
2017-01-16 01:51:01 +01:00
unsigned long NumRow ;
unsigned long NumRows ;
2017-03-07 11:03:05 +01:00
size_t MaxLength = ( Grp_MAX_BYTES_GROUP_NAME + 2 ) * Gbl . CurrentCrs . Grps . GrpTypes . NumGrpsTotal ;
2014-12-01 23:55:08 +01:00
/***** Get the names of groups which a user belongs to, from database *****/
sprintf ( Query , " SELECT crs_grp.GrpName FROM crs_grp,crs_grp_usr "
2017-03-24 01:09:27 +01:00
" WHERE crs_grp.GrpTypCod=%ld "
2015-10-26 20:02:07 +01:00
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod "
2017-03-24 01:09:27 +01:00
" AND crs_grp_usr.UsrCod=%ld "
2015-10-26 20:02:07 +01:00
" ORDER BY crs_grp.GrpName " ,
GrpTypCod , UsrCod ) ;
2014-12-01 23:55:08 +01:00
NumRows = DB_QuerySELECT ( Query , & mysql_res , " can not get the names of groups a user belongs to " ) ;
/***** Get the groups *****/
GroupNames [ 0 ] = ' \0 ' ;
for ( NumRow = 0 ;
NumRow < NumRows ;
NumRow + + )
{
/* Get next group */
row = mysql_fetch_row ( mysql_res ) ;
/* El group name in row[0] */
if ( NumRow )
2017-01-17 03:33:05 +01:00
Str_Concat ( GroupNames , " , " ,
MaxLength ) ;
Str_Concat ( GroupNames , row [ 0 ] ,
MaxLength ) ;
2014-12-01 23:55:08 +01:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult ( & mysql_res ) ;
}
/*****************************************************************************/
/****************** Receive form to create a new group type ******************/
/*****************************************************************************/
void Grp_RecFormNewGrpTyp ( void )
{
extern const char * Txt_The_type_of_group_X_already_exists ;
2017-04-29 02:20:34 +02:00
extern const char * Txt_Created_new_type_of_group_X ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_You_must_specify_the_name_of_the_new_type_of_group ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get the name of group type */
2017-01-29 12:42:19 +01:00
Par_GetParToText ( " GrpTypName " , Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2014-12-01 23:55:08 +01:00
/* Get whether it is mandatory to regisrer in any group of this type */
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MandatoryEnrolment = Par_GetParToBool ( " MandatoryEnrolment " ) ;
2014-12-01 23:55:08 +01:00
/* Get whether it is possible to register in multiple groups of this type */
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MultipleEnrolment = Par_GetParToBool ( " MultipleEnrolment " ) ;
2014-12-01 23:55:08 +01:00
/* Get open time */
2015-10-26 20:02:07 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC = Dat_GetTimeUTCFromForm ( " OpenTimeUTC " ) ;
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened = Grp_CheckIfOpenTimeInTheFuture ( Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
if ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName [ 0 ] ) // If there's a group type name
{
/***** If name of group type was in database... *****/
if ( Grp_CheckIfGroupTypeNameExists ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName , - 1L ) )
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_type_of_group_X_already_exists ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
}
else // Add new group type to database
2017-04-29 02:20:34 +02:00
{
2014-12-01 23:55:08 +01:00
Grp_CreateGroupType ( ) ;
2017-04-29 02:20:34 +02:00
2017-05-11 23:45:46 +02:00
AlertType = Ale_SUCCESS ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_Created_new_type_of_group_X ,
Gbl . CurrentCrs . 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 ;
2018-10-16 15:16:32 +02:00
Str_Copy ( Gbl . Alert . Txt , Txt_You_must_specify_the_name_of_the_new_type_of_group ,
Ale_MAX_BYTES_ALERT ) ;
2014-12-01 23:55:08 +01:00
}
/***** Show the form again *****/
2017-05-10 10:25:01 +02:00
Grp_ReqEditGroupsInternal ( AlertType , Gbl . Alert . Txt ,
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 *********************/
/*****************************************************************************/
void Grp_RecFormNewGrp ( void )
{
extern const char * Txt_The_group_X_already_exists ;
2017-04-28 18:03:30 +02:00
extern const char * Txt_Created_new_group_X ;
2014-12-01 23:55:08 +01:00
extern const char * Txt_You_must_specify_the_name_of_the_new_group ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) > 0 ) // Group type valid
{
/* Get group name */
2017-01-29 12:42:19 +01:00
Par_GetParToText ( " GrpName " , Gbl . CurrentCrs . Grps . GrpName ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME ) ;
2014-12-01 23:55:08 +01:00
/* Get maximum number of students */
2017-01-29 21:41:08 +01:00
Gbl . CurrentCrs . Grps . MaxStudents = ( unsigned )
Par_GetParToUnsignedLong ( " MaxStudents " ,
0 ,
Grp_MAX_STUDENTS_IN_A_GROUP ,
Grp_NUM_STUDENTS_NOT_LIMITED ) ;
2014-12-01 23:55:08 +01:00
if ( Gbl . CurrentCrs . Grps . GrpName [ 0 ] ) // If there's a group name
{
/***** If name of group was in database... *****/
if ( Grp_CheckIfGroupNameExists ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod , Gbl . CurrentCrs . Grps . GrpName , - 1L ) )
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_group_X_already_exists ,
Gbl . CurrentCrs . Grps . GrpName ) ;
2014-12-01 23:55:08 +01:00
}
else // Add new group to database
2017-04-28 18:03:30 +02:00
{
2014-12-01 23:55:08 +01:00
Grp_CreateGroup ( ) ;
2017-04-28 18:03:30 +02:00
/* Write success message */
2017-05-11 23:45:46 +02:00
AlertType = Ale_SUCCESS ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_Created_new_group_X ,
Gbl . CurrentCrs . 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 ;
2018-10-16 15:16:32 +02:00
Str_Copy ( Gbl . Alert . Txt , Txt_You_must_specify_the_name_of_the_new_group ,
Ale_MAX_BYTES_ALERT ) ;
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 ;
2018-10-16 15:16:32 +02:00
Str_Copy ( Gbl . Alert . Txt , " Wrong type of group. " ,
Ale_MAX_BYTES_ALERT ) ;
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 ,
2017-05-10 10:25:01 +02:00
AlertType , Gbl . Alert . Txt ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************* Check if name of group type exists **********************/
/*****************************************************************************/
static bool Grp_CheckIfGroupTypeNameExists ( const char * GrpTypName , long GrpTypCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 256 + Grp_MAX_BYTES_GROUP_TYPE_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get number of group types with a name from database *****/
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp_types "
2017-03-24 01:09:27 +01:00
" WHERE CrsCod=%ld AND GrpTypName='%s' "
" AND GrpTypCod<>%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Crs . CrsCod , GrpTypName , GrpTypCod ) ;
return ( DB_QueryCOUNT ( Query , " can not check if the name of type of group already existed " ) ! = 0 ) ;
}
/*****************************************************************************/
/************************ Check if name of group exists **********************/
/*****************************************************************************/
static bool Grp_CheckIfGroupNameExists ( long GrpTypCod , const char * GrpName , long GrpCod )
{
2017-03-11 00:47:23 +01:00
char Query [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Get number of groups with a type and a name from database *****/
sprintf ( Query , " SELECT COUNT(*) FROM crs_grp "
2017-03-24 01:09:27 +01:00
" WHERE GrpTypCod=%ld AND GrpName='%s' AND GrpCod<>%ld " ,
2014-12-01 23:55:08 +01:00
GrpTypCod , GrpName , GrpCod ) ;
return ( DB_QueryCOUNT ( Query , " can not check if the name of group already existed " ) ! = 0 ) ;
}
/*****************************************************************************/
/************************** Create a new group type **************************/
/*****************************************************************************/
static void Grp_CreateGroupType ( void )
{
2018-10-04 21:57:25 +02:00
char Query [ 1024 + Grp_MAX_BYTES_GROUP_TYPE_NAME ] ;
2014-12-01 23:55:08 +01:00
/***** Create a new group type *****/
2016-04-30 17:16:41 +02:00
sprintf ( Query , " INSERT INTO crs_grp_types "
" (CrsCod,GrpTypName,Mandatory,Multiple,MustBeOpened,OpenTime) "
2017-03-13 13:17:53 +01:00
" VALUES "
2017-03-24 01:09:27 +01:00
" (%ld,'%s','%c','%c','%c',FROM_UNIXTIME(%ld)) " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Crs . CrsCod , Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ,
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MandatoryEnrolment ? ' Y ' :
2014-12-01 23:55:08 +01:00
' N ' ,
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MultipleEnrolment ? ' Y ' :
' N ' ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened ? ' Y ' :
' N ' ,
2015-10-26 20:02:07 +01:00
( long ) Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = DB_QueryINSERTandReturnCode ( Query , " can not create type of group " ) ;
}
/*****************************************************************************/
/***************************** Create a new group ****************************/
/*****************************************************************************/
static void Grp_CreateGroup ( void )
{
2017-04-28 18:03:30 +02:00
char Query [ 256 + Grp_MAX_BYTES_GROUP_NAME ] ;
2014-12-01 23:55:08 +01:00
2017-04-28 18:03:30 +02:00
/***** Create a new group *****/
2017-03-13 13:17:53 +01:00
sprintf ( Query , " INSERT INTO crs_grp "
" (GrpTypCod,GrpName,MaxStudents,Open,FileZones) "
" VALUES "
2017-03-24 01:09:27 +01:00
" (%ld,'%s',%u,'N','N') " ,
2017-01-29 12:42:19 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ,
Gbl . CurrentCrs . Grps . GrpName ,
Gbl . CurrentCrs . Grps . MaxStudents ) ;
2014-12-01 23:55:08 +01:00
DB_QueryINSERT ( Query , " can not create group " ) ;
}
/*****************************************************************************/
/********************* Request removing of a group type **********************/
/*****************************************************************************/
void Grp_ReqRemGroupType ( void )
{
unsigned NumGrps ;
/***** Get the code of the group type *****/
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Check if this group type has groups *****/
if ( ( NumGrps = Grp_CountNumGrpsInThisCrsOfType ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ) ) // Group type has groups ==> Ask for confirmation
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 *****/
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Confirm removing *****/
Grp_AskConfirmRemGrp ( ) ;
}
/*****************************************************************************/
/********** Ask for confirmation to remove a group type with groups **********/
/*****************************************************************************/
static void Grp_AskConfirmRemGrpTypWithGrps ( unsigned NumGrps )
{
extern const char * Txt_Do_you_really_want_to_remove_the_type_of_group_X_1_group_ ;
extern const char * Txt_Do_you_really_want_to_remove_the_type_of_group_X_Y_groups_ ;
extern const char * Txt_Remove_type_of_group ;
/***** Get data of the group type from database *****/
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
2017-04-29 02:20:34 +02:00
/***** Start section to edit group types *****/
Grp_ReqEditGroupsInternal0 ( ) ;
2017-04-28 14:12:37 +02:00
/***** Show question and button to remove type of group *****/
2014-12-01 23:55:08 +01:00
if ( NumGrps = = 1 )
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_Do_you_really_want_to_remove_the_type_of_group_X_1_group_ ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
else
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_Do_you_really_want_to_remove_the_type_of_group_X_Y_groups_ ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName , NumGrps ) ;
2017-05-11 23:45:46 +02:00
Ale_ShowAlertAndButton ( Ale_QUESTION , Gbl . Alert . Txt ,
2017-05-25 14:25:22 +02:00
ActRemGrpTyp , Grp_GROUP_TYPES_SECTION_ID , NULL ,
2017-05-11 21:53:37 +02:00
Grp_PutParamRemGrpTyp ,
2017-06-11 19:02:40 +02:00
Btn_REMOVE_BUTTON , Txt_Remove_type_of_group ) ;
2017-04-28 14:12:37 +02:00
2017-04-29 02:20:34 +02:00
/***** Show the form to edit group types and groups again *****/
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal1 ( Ale_INFO , NULL ) ;
Grp_ReqEditGroupsInternal2 ( Ale_INFO , NULL ) ;
2017-04-28 14:12:37 +02:00
}
/*****************************************************************************/
/**************** Put parameter to remove a type of group ********************/
/*****************************************************************************/
static void Grp_PutParamRemGrpTyp ( void )
{
2014-12-01 23:55:08 +01:00
Grp_PutParamGrpTypCod ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
}
/*****************************************************************************/
/******************* 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 *****/
2014-12-01 23:55:08 +01:00
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
2017-04-28 13:10:46 +02:00
/***** Count number of students in group *****/
2017-05-30 21:43:05 +02:00
NumStds = Grp_CountNumUsrsInGrp ( Rol_STD , Gbl . CurrentCrs . 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 )
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_Do_you_really_want_to_remove_the_group_X ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
else if ( NumStds = = 1 )
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_Do_you_really_want_to_remove_the_group_X_1_student_ ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
else
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_Do_you_really_want_to_remove_the_group_X_Y_students_ ,
GrpDat . GrpName , NumStds ) ;
2017-05-11 23:45:46 +02:00
Ale_ShowAlertAndButton ( Ale_QUESTION , Gbl . Alert . Txt ,
2017-05-25 14:25:22 +02:00
ActRemGrp , Grp_GROUPS_SECTION_ID , NULL ,
Grp_PutParamRemGrp ,
2017-06-11 19:02:40 +02:00
Btn_REMOVE_BUTTON , Txt_Remove_group ) ;
2017-04-28 13:10:46 +02:00
2017-04-29 02:20:34 +02:00
/***** Show the form to edit groups again *****/
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal2 ( Ale_INFO , NULL ) ;
2017-04-28 13:10:46 +02:00
}
/*****************************************************************************/
/*********************** Put parameter to remove a group *********************/
/*****************************************************************************/
static void Grp_PutParamRemGrp ( void )
{
Grp_PutParamGrpCod ( Gbl . CurrentCrs . Grps . GrpCod ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-04-28 13:10:46 +02:00
/**************************** Remove a group type ****************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Grp_RemoveGroupType ( void )
{
/***** Get param with code of group type *****/
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
/***** Remove group type and its groups *****/
Grp_RemoveGroupTypeCompletely ( ) ;
}
/*****************************************************************************/
/******************************* Remove a group ******************************/
/*****************************************************************************/
void Grp_RemoveGroup ( void )
{
/***** Get param with group code *****/
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Remove group *****/
Grp_RemoveGroupCompletely ( ) ;
}
/*****************************************************************************/
2017-04-29 02:20:34 +02:00
/********************* Remove a group type from database *********************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
static void Grp_RemoveGroupTypeCompletely ( void )
{
extern const char * Txt_Type_of_group_X_removed ;
char Query [ 512 ] ;
/***** Get name and type of the group from database *****/
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
/***** Remove file zones of all the groups of this type *****/
Brw_RemoveZonesOfGroupsOfType ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
/***** Remove the associations of assignments to groups of this type *****/
Asg_RemoveGroupsOfType ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
/***** Remove the associations of attendance events to groups of this type *****/
Att_RemoveGroupsOfType ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
/***** Remove the associations of surveys to groups of this type *****/
Svy_RemoveGroupsOfType ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
/***** Change all groups of this type in course timetable *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE timetable_crs SET GrpCod=-1 "
2015-01-27 20:50:44 +01:00
" WHERE GrpCod IN "
2017-03-24 01:09:27 +01:00
" (SELECT GrpCod FROM crs_grp WHERE GrpTypCod=%ld) " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
DB_QueryUPDATE ( Query , " can not update all groups of a type in course timetable " ) ;
/***** Remove all the students in groups of this type *****/
sprintf ( Query , " DELETE FROM crs_grp_usr WHERE GrpCod IN "
2017-03-24 01:09:27 +01:00
" (SELECT GrpCod FROM crs_grp WHERE GrpTypCod=%ld) " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
DB_QueryDELETE ( Query , " can not remove users from all groups of a type " ) ;
/***** Remove all the groups of this type *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " DELETE FROM crs_grp WHERE GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
DB_QueryDELETE ( Query , " can not remove groups of a type " ) ;
/***** Remove the group type *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " DELETE FROM crs_grp_types WHERE GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
DB_QueryDELETE ( Query , " can not remove a type of group " ) ;
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_Type_of_group_X_removed ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_SUCCESS , Gbl . Alert . Txt ,
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 ;
char Query [ 512 ] ;
/***** Get name and type of the group from database *****/
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Remove file zones of this group *****/
2017-04-29 20:16:53 +02:00
Brw_RemoveGrpZones ( Gbl . CurrentCrs . Crs . CrsCod , GrpDat . GrpCod ) ;
2014-12-01 23:55:08 +01:00
/***** Remove this group from all the assignments *****/
Asg_RemoveGroup ( GrpDat . GrpCod ) ;
/***** Remove this group from all the attendance events *****/
Att_RemoveGroup ( GrpDat . GrpCod ) ;
/***** Remove this group from all the surveys *****/
Svy_RemoveGroup ( GrpDat . GrpCod ) ;
/***** Change this group in course timetable *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE timetable_crs SET GrpCod=-1 WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not update a group in course timetable " ) ;
/***** Remove all the students in this group *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " DELETE FROM crs_grp_usr WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryDELETE ( Query , " can not remove users from a group " ) ;
/***** Remove the group *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " DELETE FROM crs_grp WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryDELETE ( Query , " can not remove a group " ) ;
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_Group_X_removed ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
Ale_SUCCESS , Gbl . Alert . Txt ) ;
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 ;
char Query [ 512 ] ;
/***** Get group code *****/
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Get group data from database *****/
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Update the table of groups changing open/close status *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET Open='Y' WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not open a group " ) ;
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_group_X_is_now_open ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
Gbl . CurrentCrs . Grps . Open = true ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
Ale_SUCCESS , Gbl . Alert . Txt ) ;
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 ;
char Query [ 512 ] ;
/***** Get group code *****/
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Get group data from database *****/
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Update the table of groups changing open/close status *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET Open='N' WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not close a group " ) ;
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_group_X_is_now_closed ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
Gbl . CurrentCrs . Grps . Open = false ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
Ale_SUCCESS , Gbl . Alert . Txt ) ;
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 ;
char Query [ 512 ] ;
/***** Get group code *****/
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Get group data from database *****/
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Update the table of groups changing file zones status *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET FileZones='Y' WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not enable file zones of a group " ) ;
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_File_zones_of_the_group_X_are_now_enabled ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
Gbl . CurrentCrs . Grps . FileZones = true ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
Ale_SUCCESS , Gbl . Alert . Txt ) ;
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 ;
char Query [ 512 ] ;
/***** Get group code *****/
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/***** Get group data from database *****/
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Update the table of groups changing file zones status *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET FileZones='N' WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not disable file zones of a group " ) ;
2018-10-16 21:56:01 +02:00
/***** Create message to show the change made *****/
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
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 *****/
Gbl . CurrentCrs . Grps . FileZones = false ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
Ale_SUCCESS , Gbl . Alert . Txt ) ;
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 ;
char Query [ 512 ] ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get group code */
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/* Get the new group type */
NewGrpTypCod = Grp_GetParamGrpTypCod ( ) ;
/* Get from the database the type and the name of the group */
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** If group was in database... *****/
if ( Grp_CheckIfGroupNameExists ( NewGrpTypCod , GrpDat . GrpName , - 1L ) )
{
2018-10-16 21:56:01 +02:00
/* Create warning message */
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_group_X_already_exists ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
}
2018-10-16 21:56:01 +02:00
else // Group is not in database
2014-12-01 23:55:08 +01:00
{
/* Update the table of groups changing old type by new type */
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET GrpTypCod=%ld WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
NewGrpTypCod , Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not update the type of a group " ) ;
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 ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
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 *****/
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = NewGrpTypCod ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2017-05-10 10:25:01 +02:00
AlertType , Gbl . Alert . Txt ) ;
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 ;
2014-12-01 23:55:08 +01:00
char Query [ 1024 ] ;
2017-03-30 11:20:06 +02:00
bool NewMandatoryEnrolment ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters of the form *****/
/* Get the c<> digo of type of group */
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
2017-03-30 11:20:06 +02:00
/* Get the new type of enrolment (mandatory or voluntaria) of this type of group */
NewMandatoryEnrolment = Par_GetParToBool ( " MandatoryEnrolment " ) ;
2014-12-01 23:55:08 +01:00
2017-03-30 11:20:06 +02:00
/* Get from the database the name of the type and the old type of enrolment */
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
2017-03-30 11:20:06 +02:00
/***** Check if the old type of enrolment match the new
2014-12-01 23:55:08 +01:00
( this happens when return is pressed without changes in the form ) * * * * */
2017-03-30 11:20:06 +02:00
if ( Gbl . CurrentCrs . Grps . GrpTyp . MandatoryEnrolment = = NewMandatoryEnrolment )
2014-12-01 23:55:08 +01:00
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_INFO ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_type_of_enrolment_of_the_type_of_group_X_has_not_changed ,
Gbl . CurrentCrs . 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 *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp_types SET Mandatory='%c' WHERE GrpTypCod=%ld " ,
2017-03-30 11:20:06 +02:00
NewMandatoryEnrolment ? ' Y ' :
2014-12-01 23:55:08 +01:00
' N ' ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
2017-03-30 11:20:06 +02:00
DB_QueryUPDATE ( Query , " can not update enrolment type of a type of group " ) ;
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 ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
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 ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
}
/***** Show the form again *****/
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MandatoryEnrolment = NewMandatoryEnrolment ;
2017-05-10 10:25:01 +02:00
Grp_ReqEditGroupsInternal ( AlertType , Gbl . Alert . Txt ,
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 ;
char Query [ 1024 ] ;
2017-03-30 11:20:06 +02:00
bool NewMultipleEnrolment ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from the form *****/
/* Get the code of type of group */
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
2017-03-30 11:20:06 +02:00
/* Get the new type of enrolment (single or multiple) of this type of group */
NewMultipleEnrolment = Par_GetParToBool ( " MultipleEnrolment " ) ;
2014-12-01 23:55:08 +01:00
2017-03-30 11:20:06 +02:00
/* Get from the database the name of the type and the old type of enrolment */
2014-12-01 23:55:08 +01:00
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
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 ) * * * * */
2017-03-30 11:20:06 +02:00
if ( Gbl . CurrentCrs . Grps . GrpTyp . MultipleEnrolment = = NewMultipleEnrolment )
2014-12-01 23:55:08 +01:00
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_INFO ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_type_of_enrolment_of_the_type_of_group_X_has_not_changed ,
Gbl . CurrentCrs . 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 *****/
2014-12-01 23:55:08 +01:00
sprintf ( Query , " UPDATE crs_grp_types SET Multiple='%c' "
2017-03-24 01:09:27 +01:00
" WHERE GrpTypCod=%ld " ,
2017-03-30 11:20:06 +02:00
NewMultipleEnrolment ? ' Y ' :
' N ' ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
2017-03-30 11:20:06 +02:00
DB_QueryUPDATE ( Query , " can not update enrolment type of a type of group " ) ;
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 ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
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 ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
}
/***** Show the form again *****/
2017-03-30 11:20:06 +02:00
Gbl . CurrentCrs . Grps . GrpTyp . MultipleEnrolment = NewMultipleEnrolment ;
2017-05-10 10:25:01 +02:00
Grp_ReqEditGroupsInternal ( AlertType , Gbl . Alert . Txt ,
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 ;
char Query [ 512 ] ;
/***** Get the code of type of group *****/
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
/***** Get from the database the data of this type of group *****/
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
/***** Get open time *****/
2015-10-26 20:02:07 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC = Dat_GetTimeUTCFromForm ( " OpenTimeUTC " ) ;
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened = Grp_CheckIfOpenTimeInTheFuture ( Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC ) ;
2014-12-01 23:55:08 +01:00
2016-04-30 17:16:41 +02:00
/***** Update the table of types of group
2017-03-30 11:20:06 +02:00
changing the old open time of enrolment by the new * * * * */
2016-04-30 17:16:41 +02:00
sprintf ( Query , " UPDATE crs_grp_types "
2017-03-24 01:09:27 +01:00
" SET MustBeOpened='%c',OpenTime=FROM_UNIXTIME(%ld) "
" WHERE GrpTypCod=%ld " ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . MustBeOpened ? ' Y ' :
' N ' ,
2015-10-26 20:02:07 +01:00
( long ) Gbl . CurrentCrs . Grps . GrpTyp . OpenTimeUTC ,
2014-12-01 23:55:08 +01:00
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
2017-03-30 11:20:06 +02:00
DB_QueryUPDATE ( Query , " can not update enrolment type of a type of group " ) ;
2014-12-01 23:55:08 +01:00
/***** Write message to show the change made *****/
2018-10-16 15:16:32 +02: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 *****/
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_SUCCESS , Gbl . Alert . Txt ,
Ale_INFO , NULL ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************** Change maximum of students in a group *********************/
/*****************************************************************************/
void Grp_ChangeMaxStdsGrp ( void )
{
extern const char * Txt_The_maximum_number_of_students_in_the_group_X_has_not_changed ;
extern const char * Txt_The_group_X_now_has_no_limit_of_students ;
extern const char * Txt_The_maximum_number_of_students_in_the_group_X_is_now_Y ;
struct GroupData GrpDat ;
char Query [ 1024 ] ;
unsigned NewMaxStds ;
2017-05-11 23:45:46 +02:00
Ale_AlertType_t AlertType ;
2014-12-01 23:55:08 +01:00
/***** Get parameters of the form *****/
/* Get group code */
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1 )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/* Get the new maximum number of students of the group */
2017-01-29 21:41:08 +01:00
NewMaxStds = ( unsigned )
Par_GetParToUnsignedLong ( " MaxStudents " ,
0 ,
Grp_MAX_STUDENTS_IN_A_GROUP ,
Grp_NUM_STUDENTS_NOT_LIMITED ) ;
2014-12-01 23:55:08 +01:00
/* Get from the database the type, name, and antiguo maximum of students of the group */
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Check if the old maximum of students equals the new one (this happens when user press return without change the form) *****/
if ( GrpDat . MaxStudents = = NewMaxStds )
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_INFO ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_maximum_number_of_students_in_the_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 *****/
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET MaxStudents=%u WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
NewMaxStds , Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not update the maximum number of students in a group " ) ;
/***** 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 )
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_group_X_now_has_no_limit_of_students ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
else
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_maximum_number_of_students_in_the_group_X_is_now_Y ,
GrpDat . GrpName , NewMaxStds ) ;
2014-12-01 23:55:08 +01:00
}
/***** Show the form again *****/
Gbl . CurrentCrs . Grps . MaxStudents = NewMaxStds ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2017-05-10 10:25:01 +02:00
AlertType , Gbl . Alert . Txt ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************ Write the number maximum of students in a group ***************/
/*****************************************************************************/
static void Grp_WriteMaxStdsGrp ( unsigned MaxStudents )
{
2017-05-30 21:43:05 +02:00
if ( MaxStudents < = Grp_MAX_STUDENTS_IN_A_GROUP )
2014-12-01 23:55:08 +01:00
fprintf ( Gbl . F . Out , " %u " , MaxStudents ) ;
}
/*****************************************************************************/
/********* 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 )
{
extern const char * Txt_You_can_not_leave_the_name_of_the_type_of_group_X_empty ;
extern const char * Txt_The_type_of_group_X_already_exists ;
extern const char * Txt_The_type_of_group_X_has_been_renamed_as_Y ;
extern const char * Txt_The_name_of_the_type_of_group_X_has_not_changed ;
2017-03-11 00:47:23 +01:00
char Query [ 128 + Grp_MAX_BYTES_GROUP_TYPE_NAME ] ;
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 ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get the code of the group type */
if ( ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod = Grp_GetParamGrpTypCod ( ) ) < 0 )
Lay_ShowErrorAndExit ( " Code of type of group is missing. " ) ;
/* Get the new name for the group type */
2017-03-07 11:03:05 +01:00
Par_GetParToText ( " GrpTypName " , NewNameGrpTyp , Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2014-12-01 23:55:08 +01:00
/***** Get from the database the old name of the group type *****/
Grp_GetDataOfGroupTypeByCod ( & Gbl . CurrentCrs . Grps . GrpTyp ) ;
/***** Check if new name is empty *****/
if ( ! NewNameGrpTyp [ 0 ] )
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_You_can_not_leave_the_name_of_the_type_of_group_X_empty ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName ) ;
2014-12-01 23:55:08 +01:00
}
else
{
/***** Check if old and new names are the same (this happens when user press enter with no changes in the form) *****/
if ( strcmp ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName , NewNameGrpTyp ) ) // Different names
{
/***** If group type was in database... *****/
if ( Grp_CheckIfGroupTypeNameExists ( NewNameGrpTyp , Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) )
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_type_of_group_X_already_exists ,
NewNameGrpTyp ) ;
2014-12-01 23:55:08 +01:00
}
else
{
/* Update the table changing old name by new name */
2017-03-11 00:47:23 +01:00
sprintf ( Query , " UPDATE crs_grp_types SET GrpTypName='%s' "
2017-03-24 01:09:27 +01:00
" WHERE GrpTypCod=%ld " ,
2016-04-30 17:16:41 +02:00
NewNameGrpTyp ,
Gbl . CurrentCrs . Grps . GrpTyp . GrpTypCod ) ;
2014-12-01 23:55:08 +01:00
DB_QueryUPDATE ( Query , " can not update the type of a group " ) ;
/***** Write message to show the change made *****/
2017-05-11 23:45:46 +02:00
AlertType = Ale_SUCCESS ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_type_of_group_X_has_been_renamed_as_Y ,
Gbl . CurrentCrs . 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 ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_name_of_the_type_of_group_X_has_not_changed ,
NewNameGrpTyp ) ;
2014-12-01 23:55:08 +01:00
}
}
/***** Show the form again *****/
2017-01-15 18:02:52 +01:00
Str_Copy ( Gbl . CurrentCrs . Grps . GrpTyp . GrpTypName , NewNameGrpTyp ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME ) ;
2017-05-10 10:25:01 +02:00
Grp_ReqEditGroupsInternal ( AlertType , Gbl . Alert . Txt ,
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 )
{
extern const char * Txt_You_can_not_leave_the_name_of_the_group_X_empty ;
extern const char * Txt_The_group_X_already_exists ;
extern const char * Txt_The_group_X_has_been_renamed_as_Y ;
extern const char * Txt_The_name_of_the_group_X_has_not_changed ;
struct GroupData GrpDat ;
2017-03-11 00:47:23 +01:00
char Query [ 128 + Grp_MAX_BYTES_GROUP_NAME ] ;
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 ;
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get the code of the group */
if ( ( Gbl . CurrentCrs . Grps . GrpCod = Grp_GetParamGrpCod ( ) ) = = - 1L )
Lay_ShowErrorAndExit ( " Code of group is missing. " ) ;
/* Get the new name for the group */
2017-03-07 11:03:05 +01:00
Par_GetParToText ( " GrpName " , NewNameGrp , Grp_MAX_BYTES_GROUP_NAME ) ;
2014-12-01 23:55:08 +01:00
/***** Get from the database the type and the old name of the group *****/
GrpDat . GrpCod = Gbl . CurrentCrs . Grps . GrpCod ;
Grp_GetDataOfGroupByCod ( & GrpDat ) ;
/***** Check if new name is empty *****/
if ( ! NewNameGrp [ 0 ] )
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_You_can_not_leave_the_name_of_the_group_X_empty ,
GrpDat . GrpName ) ;
2014-12-01 23:55:08 +01:00
}
else
{
/***** Check if old and new names are the same (this happens when user press enter with no changes in the form) *****/
if ( strcmp ( GrpDat . GrpName , NewNameGrp ) ) // Different names
{
/***** If group was in database... *****/
if ( Grp_CheckIfGroupNameExists ( GrpDat . GrpTypCod , NewNameGrp , Gbl . CurrentCrs . Grps . GrpCod ) )
{
2017-05-11 23:45:46 +02:00
AlertType = Ale_WARNING ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_group_X_already_exists ,
NewNameGrp ) ;
2014-12-01 23:55:08 +01:00
}
else
{
/* Update the table changing old name by new name */
2017-03-24 01:09:27 +01:00
sprintf ( Query , " UPDATE crs_grp SET GrpName='%s' WHERE GrpCod=%ld " ,
2014-12-01 23:55:08 +01:00
NewNameGrp , Gbl . CurrentCrs . Grps . GrpCod ) ;
DB_QueryUPDATE ( Query , " can not update the name of a group " ) ;
/***** Write message to show the change made *****/
2017-05-11 23:45:46 +02:00
AlertType = Ale_SUCCESS ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
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 ;
2018-10-16 23:08:04 +02:00
snprintf ( Gbl . Alert . Txt , sizeof ( Gbl . Alert . Txt ) ,
2018-10-16 21:56:01 +02:00
Txt_The_name_of_the_group_X_has_not_changed ,
NewNameGrp ) ;
2014-12-01 23:55:08 +01:00
}
}
/***** Show the form again *****/
2017-01-17 03:10:43 +01:00
Str_Copy ( Gbl . CurrentCrs . Grps . GrpName , NewNameGrp ,
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME ) ;
2017-05-11 23:45:46 +02:00
Grp_ReqEditGroupsInternal ( Ale_INFO , NULL ,
2017-05-10 10:25:01 +02:00
AlertType , Gbl . Alert . Txt ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************* Get parameter with code of group type *******************/
/*****************************************************************************/
static long Grp_GetParamGrpTypCod ( void )
{
2017-01-28 20:32:50 +01:00
/***** Get code of group type *****/
return Par_GetParToLong ( " GrpTypCod " ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Get parameter with group code ***********************/
/*****************************************************************************/
static long Grp_GetParamGrpCod ( void )
{
2017-01-28 20:32:50 +01:00
/***** Get group code *****/
return Par_GetParToLong ( " GrpCod " ) ;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****************** Write parameter with code of group type ******************/
/*****************************************************************************/
static void Grp_PutParamGrpTypCod ( long GrpTypCod )
{
Par_PutHiddenParamLong ( " GrpTypCod " , GrpTypCod ) ;
}
/*****************************************************************************/
/********************* Write parameter with code of group ********************/
/*****************************************************************************/
void Grp_PutParamGrpCod ( long GrpCod )
{
Par_PutHiddenParamLong ( " GrpCod " , GrpCod ) ;
}
/*****************************************************************************/
/************************ Get list of group codes selected *******************/
/*****************************************************************************/
void Grp_GetLstCodsGrpWanted ( struct ListCodGrps * LstGrpsWanted )
{
unsigned NumGrpTyp ;
2017-01-28 15:58:46 +01:00
char Param [ 8 + 10 + 1 ] ;
char LongStr [ 1 + 10 + 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 *****/
if ( ( LstStrCodGrps = ( char * * ) calloc ( Gbl . CurrentCrs . Grps . GrpTypes . Num , sizeof ( char * ) ) ) = = NULL )
2017-03-30 11:20:06 +02:00
Lay_ShowErrorAndExit ( " Not enough memory to store codes of groups in which a user wants to be enroled. " ) ;
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 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
/***** Allocate memory for the list of group codes of this type *****/
2017-01-28 15:58:46 +01:00
if ( ( LstStrCodGrps [ NumGrpTyp ] = ( char * ) malloc ( ( size_t ) ( ( 1 + 10 + 1 ) *
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . NumGrps ) ) ) = = NULL )
2017-03-30 11:20:06 +02:00
Lay_ShowErrorAndExit ( " Not enough memory to store codes of groups in which a user wants to be enroled. " ) ;
2014-12-01 23:55:08 +01:00
/***** Get the multiple parameter code of group of this type *****/
2017-06-20 01:58:16 +02:00
sprintf ( Param , " GrpCod%ld " ,
Gbl . CurrentCrs . Grps . GrpTypes . LstGrpTypes [ NumGrpTyp ] . GrpTypCod ) ;
2017-01-28 15:58:46 +01:00
Par_GetParMultiToText ( Param , LstStrCodGrps [ NumGrpTyp ] ,
( ( 1 + 10 + 1 ) * Gbl . CurrentCrs . 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 + + )
2017-01-28 15:58:46 +01:00
Par_GetNextStrUntilSeparParamMult ( & Ptr , LongStr , 1 + 10 ) ;
2014-12-01 23:55:08 +01:00
/***** Add the number of groups selected of this type to the number of groups selected total *****/
LstGrpsWanted - > NumGrps + = NumGrpWanted ;
}
}
/***** Create the list (argument passed to this function)
with all the groups selected ( of all the types ) * * * * */
if ( LstGrpsWanted - > NumGrps )
{
2017-01-19 20:55:31 +01:00
if ( ( LstGrpsWanted - > GrpCods = ( long * ) calloc ( LstGrpsWanted - > NumGrps , sizeof ( long ) ) ) = = NULL )
2017-03-30 11:20:06 +02:00
Lay_ShowErrorAndExit ( " Not enoguh memory to store codes of groups in which a user wants to be enroled. " ) ;
2014-12-01 23:55:08 +01:00
/***** Get the groups *****/
for ( NumGrpTyp = 0 , NumGrpWanted = 0 ;
NumGrpTyp < Gbl . CurrentCrs . Grps . GrpTypes . Num ;
NumGrpTyp + + )
{
/* Add the groups selected of this type to the complete list of groups selected */
for ( Ptr = LstStrCodGrps [ NumGrpTyp ] ;
* Ptr ;
NumGrpWanted + + )
{
2017-01-28 15:58:46 +01:00
Par_GetNextStrUntilSeparParamMult ( & Ptr , LongStr , 1 + 10 ) ;
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 */
free ( ( void * ) LstStrCodGrps [ NumGrpTyp ] ) ;
}
}
/***** Free memory used by the lists of group codes of each type *****/
free ( ( void * ) LstStrCodGrps ) ;
}
/*****************************************************************************/
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 )
free ( ( void * ) LstGrps - > GrpCods ) ;
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
/*****************************************************************************/
void Grp_PutParamWhichGrps ( void )
{
Grp_GetParamWhichGrps ( ) ;
Par_PutHiddenParamUnsigned ( " WhichGrps " , ( unsigned ) Gbl . CurrentCrs . Grps . WhichGrps ) ;
}
2016-12-04 20:12:56 +01:00
void Grp_PutParamWhichGrpsOnlyMyGrps ( void )
{
Par_PutHiddenParamUnsigned ( " WhichGrps " , ( unsigned ) Grp_ONLY_MY_GROUPS ) ;
}
void Grp_PutParamWhichGrpsAllGrps ( void )
{
Par_PutHiddenParamUnsigned ( " WhichGrps " , ( unsigned ) Grp_ALL_GROUPS ) ;
}
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
/*****************************************************************************/
2016-12-04 23:09:28 +01:00
void Grp_ShowFormToSelWhichGrps ( Act_Action_t Action , void ( * FuncParams ) ( ) )
{
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 ;
2016-12-23 22:19:03 +01:00
fprintf ( Gbl . F . Out , " <div class= \" PREF_CONTAINER \" > " ) ;
2016-12-04 23:09:28 +01:00
for ( WhichGrps = Grp_ONLY_MY_GROUPS ;
WhichGrps < = Grp_ALL_GROUPS ;
WhichGrps + + )
{
2016-12-23 22:19:03 +01:00
fprintf ( Gbl . F . Out , " <div class= \" %s \" > " ,
2016-12-04 23:09:28 +01:00
WhichGrps = = Gbl . CurrentCrs . Grps . WhichGrps ? " PREF_ON " :
" PREF_OFF " ) ;
2018-10-15 14:07:12 +02:00
Act_StartForm ( Action ) ;
2016-12-04 23:09:28 +01:00
Par_PutHiddenParamUnsigned ( " WhichGrps " , ( unsigned ) WhichGrps ) ;
if ( FuncParams ) // Extra parameters depending on the action
FuncParams ( ) ;
fprintf ( Gbl . F . Out , " <input type= \" image \" src= \" %s/%s \" "
" alt= \" %s \" title= \" %s \" class= \" ICO25x25 \" "
" style= \" margin:0 auto; \" /> " ,
Gbl . Prefs . IconsURL ,
WhichGrps = = Grp_ONLY_MY_GROUPS ? " myhierarchy64x64.png " :
" hierarchy64x64.png " ,
2017-03-21 00:57:11 +01:00
Txt_GROUP_WHICH_GROUPS [ WhichGrps ] ,
Txt_GROUP_WHICH_GROUPS [ WhichGrps ] ) ;
2018-10-15 14:07:12 +02:00
Act_EndForm ( ) ;
2016-12-04 23:09:28 +01:00
fprintf ( Gbl . F . Out , " </div> " ) ;
}
fprintf ( Gbl . F . Out , " </div> " ) ;
}
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
/*****************************************************************************/
void Grp_GetParamWhichGrps ( void )
{
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 )
{
case ActSeeCrsTT :
case ActPrnCrsTT :
case ActChgCrsTT1stDay :
case ActSeeAsg :
case ActSeeAllSvy :
2017-04-27 10:15:07 +02:00
case ActSeeAtt :
2017-01-29 12:42:19 +01:00
WhichGroupsDefault = Gbl . Usrs . Me . IBelongToCurrentCrs ? Grp_ONLY_MY_GROUPS : // If I belong to this course ==> see only my groups
Grp_ALL_GROUPS ; // If I don't belong to this course ==> see all groups
break ;
case ActSeeMyTT :
case ActPrnMyTT :
case ActChgMyTT1stDay :
WhichGroupsDefault = Grp_ONLY_MY_GROUPS ; // By default, see only my groups
break ;
default : // Control never should enter here
WhichGroupsDefault = Grp_WHICH_GROUPS_DEFAULT ;
break ;
}
/* Get parameter */
Gbl . CurrentCrs . Grps . WhichGrps = ( Grp_WhichGroups_t )
2017-01-29 21:41:08 +01: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
}
}