swad-core/swad_course.c

3523 lines
125 KiB
C
Raw Normal View History

2014-12-01 23:55:08 +01:00
// swad_course.c: edition of courses
/*
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.
2019-01-07 21:52:19 +01:00
Copyright (C) 1999-2019 Antonio Ca<EFBFBD>as Vargas
2014-12-01 23:55:08 +01:00
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
2018-10-20 12:03:57 +02:00
#define _GNU_SOURCE // For asprintf
2014-12-01 23:55:08 +01:00
#include <linux/limits.h> // For PATH_MAX
#include <linux/stddef.h> // For NULL
#include <limits.h> // For maximum values
2018-10-20 12:03:57 +02:00
#include <stdio.h> // For asprintf
2014-12-01 23:55:08 +01:00
#include <stdlib.h> // For getenv, etc.
#include <string.h> // For string functions
2017-06-10 21:38:10 +02:00
#include "swad_box.h"
2014-12-01 23:55:08 +01:00
#include "swad_course.h"
#include "swad_constant.h"
#include "swad_database.h"
#include "swad_degree.h"
2017-03-30 11:20:06 +02:00
#include "swad_enrolment.h"
2014-12-01 23:55:08 +01:00
#include "swad_exam.h"
2018-11-09 20:47:39 +01:00
#include "swad_form.h"
2014-12-01 23:55:08 +01:00
#include "swad_global.h"
2015-10-06 20:34:49 +02:00
#include "swad_help.h"
2016-11-14 16:47:46 +01:00
#include "swad_hierarchy.h"
2014-12-01 23:55:08 +01:00
#include "swad_indicator.h"
2015-01-17 20:06:25 +01:00
#include "swad_logo.h"
2014-12-01 23:55:08 +01:00
#include "swad_notification.h"
#include "swad_parameter.h"
#include "swad_QR.h"
2017-05-29 13:20:48 +02:00
#include "swad_role.h"
2014-12-01 23:55:08 +01:00
#include "swad_RSS.h"
2015-01-04 15:48:24 +01:00
#include "swad_tab.h"
2017-06-11 20:09:59 +02:00
#include "swad_table.h"
2014-12-01 23:55:08 +01:00
#include "swad_theme.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/*************************** Public constants ********************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private types *********************************/
/*****************************************************************************/
/*****************************************************************************/
2019-04-07 19:49:53 +02:00
/**************************** Private variables ******************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-04-08 23:34:58 +02:00
static struct Course *Crs_EditingCrs = NULL; // Static variable to keep the course being edited
2019-04-07 19:49:53 +02:00
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/**************************** Private prototypes *****************************/
/*****************************************************************************/
static void Crs_Configuration (bool PrintView);
2016-03-18 19:23:30 +01:00
static void Crs_PutIconToPrint (void);
2017-05-21 14:43:10 +02:00
static void Crs_ShowNumUsrsInCrs (Rol_Role_t Role);
2014-12-01 23:55:08 +01:00
static void Crs_WriteListMyCoursesToSelectOne (void);
2019-04-03 20:57:04 +02:00
static void Crs_GetListCoursesInCurrentDegree (Crs_WhatCourses_t WhatCourses);
2014-12-01 23:55:08 +01:00
static void Crs_ListCourses (void);
2016-11-07 00:03:50 +01:00
static bool Crs_CheckIfICanCreateCourses (void);
static void Crs_PutIconsListCourses (void);
2016-03-16 22:40:35 +01:00
static void Crs_PutIconToEditCourses (void);
2015-12-06 14:18:07 +01:00
static bool Crs_ListCoursesOfAYearForSeeing (unsigned Year);
2016-03-20 12:35:27 +01:00
2019-04-07 19:49:53 +02:00
static void Crs_EditCoursesInternal (void);
2018-11-15 18:51:13 +01:00
static void Crs_PutIconsEditingCourses (void);
2017-04-30 12:44:53 +02:00
static void Crs_PutIconToViewCourses (void);
2014-12-01 23:55:08 +01:00
static void Crs_ListCoursesForEdition (void);
2016-07-04 09:54:36 +02:00
static void Crs_ListCoursesOfAYearForEdition (unsigned Year);
2014-12-01 23:55:08 +01:00
static bool Crs_CheckIfICanEdit (struct Course *Crs);
static Crs_StatusTxt_t Crs_GetStatusTxtFromStatusBits (Crs_Status_t Status);
static Crs_Status_t Crs_GetStatusBitsFromStatusTxt (Crs_StatusTxt_t StatusTxt);
static void Crs_PutFormToCreateCourse (void);
static void Crs_PutHeadCoursesForSeeing (void);
static void Crs_PutHeadCoursesForEdition (void);
static void Crs_RecFormRequestOrCreateCrs (unsigned Status);
static void Crs_GetParamsNewCourse (struct Course *Crs);
2017-03-09 11:16:17 +01:00
2017-05-11 20:04:38 +02:00
static void Crs_CreateCourse (unsigned Status);
2014-12-01 23:55:08 +01:00
static void Crs_GetDataOfCourseFromRow (struct Course *Crs,MYSQL_ROW row);
2016-06-12 01:18:35 +02:00
2016-10-20 16:49:42 +02:00
static void Crs_UpdateCrsDegDB (long CrsCod,long DegCod);
2016-10-19 19:21:26 +02:00
2016-06-12 01:18:35 +02:00
static void Crs_UpdateCrsYear (struct Course *Crs,unsigned NewYear);
2017-01-13 01:51:23 +01:00
static void Crs_GetShortNamesByCod (long CrsCod,
2017-03-08 14:12:33 +01:00
char CrsShortName[Hie_MAX_BYTES_SHRT_NAME + 1],
char DegShortName[Hie_MAX_BYTES_SHRT_NAME + 1]);
2017-01-13 01:51:23 +01:00
2014-12-01 23:55:08 +01:00
static void Crs_EmptyCourseCompletely (long CrsCod);
2016-10-23 17:20:06 +02:00
2016-10-28 10:03:37 +02:00
static void Crs_RenameCourse (struct Course *Crs,Cns_ShrtOrFullName_t ShrtOrFullName);
2017-03-09 11:16:17 +01:00
static bool Crs_CheckIfCrsNameExistsInYearOfDeg (const char *FieldName,const char *Name,long CrsCod,
long DegCod,unsigned Year);
static void Crs_UpdateCrsNameDB (long CrsCod,const char *FieldName,const char *NewCrsName);
2017-05-11 20:55:04 +02:00
static void Crs_PutButtonToGoToCrs (void);
static void Crs_PutButtonToRegisterInCrs (void);
2015-04-02 18:39:49 +02:00
2018-10-09 13:08:41 +02:00
static void Crs_PutIconToSearchCourses (void);
2016-06-24 20:34:58 +02:00
static void Sch_PutLinkToSearchCoursesParams (void);
2014-12-01 23:55:08 +01:00
static void Crs_PutParamOtherCrsCod (long CrsCod);
2017-05-31 21:05:59 +02:00
static long Crs_GetAndCheckParamOtherCrsCod (long MinCodAllowed);
2014-12-01 23:55:08 +01:00
static void Crs_WriteRowCrsData (unsigned NumCrs,MYSQL_ROW row,bool WriteColumnAccepted);
2019-04-07 19:49:53 +02:00
static void Crs_EditingCourseConstructor (void);
static void Crs_EditingCourseDestructor (void);
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/***************** Show introduction to the current course *******************/
/*****************************************************************************/
void Crs_ShowIntroduction (void)
{
/***** Course configuration *****/
2015-10-06 23:47:34 +02:00
fprintf (Gbl.F.Out,"<div class=\"CENTER_MIDDLE\">");
2014-12-01 23:55:08 +01:00
Crs_Configuration (false);
fprintf (Gbl.F.Out,"</div>");
/***** Course introduction *****/
Inf_ShowInfo ();
2015-10-06 01:19:21 +02:00
2017-03-30 11:20:06 +02:00
/***** Show help to enrol me *****/
2015-12-06 14:18:07 +01:00
Hlp_ShowHelpWhatWouldYouLikeToDo ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************** Print configuration of the current course *****************/
/*****************************************************************************/
void Crs_PrintConfiguration (void)
{
Crs_Configuration (true);
}
/*****************************************************************************/
/***************** Configuration of the current course ***********************/
/*****************************************************************************/
static void Crs_Configuration (bool PrintView)
{
2016-11-13 16:59:04 +01:00
extern const char *Hlp_COURSE_Information;
2019-02-22 21:47:50 +01:00
extern const char *The_ClassFormInBox[The_NUM_THEMES];
2016-10-19 01:46:40 +02:00
extern const char *Txt_Degree;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Course;
2015-02-04 20:03:23 +01:00
extern const char *Txt_Short_name;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Year_OF_A_DEGREE;
2017-01-28 15:58:46 +01:00
extern const char *Txt_YEAR_OF_DEGREE[1 + Deg_MAX_YEARS_PER_DEGREE];
2015-12-06 14:18:07 +01:00
extern const char *Txt_Not_applicable;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Institutional_code;
extern const char *Txt_Internal_code;
2015-03-07 18:09:42 +01:00
extern const char *Txt_Shortcut;
2018-12-08 16:43:13 +01:00
extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES];
2014-12-01 23:55:08 +01:00
extern const char *Txt_QR_code;
extern const char *Txt_Indicators;
extern const char *Txt_of_PART_OF_A_TOTAL;
2016-10-19 01:46:40 +02:00
unsigned NumDeg;
2014-12-01 23:55:08 +01:00
unsigned Year;
2016-06-10 10:22:22 +02:00
int NumIndicatorsFromDB;
struct Ind_IndicatorsCrs Indicators;
2019-04-03 20:57:04 +02:00
bool IsForm;
bool PutLink;
/***** Trivial check *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Crs.CrsCod <= 0) // No course selected
2019-04-03 20:57:04 +02:00
return;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** Messages and links above the box *****/
2014-12-08 17:35:48 +01:00
if (!PrintView)
2014-12-01 23:55:08 +01:00
{
2017-03-30 11:20:06 +02:00
/* Link to request enrolment in the current course */
2017-06-04 18:18:54 +02:00
if (Gbl.Usrs.Me.Role.Logged == Rol_GST ||
Gbl.Usrs.Me.Role.Logged == Rol_USR)
2016-03-18 19:23:30 +01:00
{
fprintf (Gbl.F.Out,"<div class=\"CONTEXT_MENU\">");
2015-01-16 12:11:27 +01:00
Enr_PutLinkToRequestSignUp ();
2016-03-18 19:23:30 +01:00
fprintf (Gbl.F.Out,"</div>");
}
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
if (PrintView)
Box_StartBox (NULL,NULL,NULL,
2017-06-12 15:03:29 +02:00
NULL,Box_NOT_CLOSABLE);
2017-06-11 22:26:40 +02:00
else
Box_StartBox (NULL,NULL,Crs_PutIconToPrint,
2017-06-12 15:03:29 +02:00
Hlp_COURSE_Information,Box_NOT_CLOSABLE);
2014-12-08 17:35:48 +01:00
2014-12-01 23:55:08 +01:00
/***** Title *****/
2019-04-03 20:57:04 +02:00
PutLink = !PrintView && Gbl.Hierarchy.Deg.WWW[0];
2016-11-23 23:58:46 +01:00
fprintf (Gbl.F.Out,"<div class=\"FRAME_TITLE FRAME_TITLE_BIG\">");
2014-12-01 23:55:08 +01:00
if (PutLink)
fprintf (Gbl.F.Out,"<a href=\"%s\" target=\"_blank\""
2016-11-23 23:58:46 +01:00
" class=\"FRAME_TITLE_BIG\" title=\"%s\">",
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Deg.WWW,
Gbl.Hierarchy.Deg.FullName);
Log_DrawLogo (Hie_DEG,Gbl.Hierarchy.Deg.DegCod,
Gbl.Hierarchy.Deg.ShrtName,64,NULL,true);
2014-12-01 23:55:08 +01:00
if (PutLink)
fprintf (Gbl.F.Out,"</a>");
fprintf (Gbl.F.Out,"<br />%s"
2016-03-18 19:23:30 +01:00
"</div>",
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.FullName);
2014-12-01 23:55:08 +01:00
2016-03-18 19:23:30 +01:00
/***** Start table *****/
2017-06-11 20:09:59 +02:00
Tbl_StartTableWide (2);
2016-03-18 19:23:30 +01:00
2016-10-19 20:43:26 +02:00
/***** Degree *****/
2016-10-19 01:46:40 +02:00
fprintf (Gbl.F.Out,"<tr>"
2016-12-21 00:45:51 +01:00
"<td class=\"RIGHT_MIDDLE\">"
"<label for=\"OthDegCod\" class=\"%s\">%s:</label>"
2016-10-19 01:46:40 +02:00
"</td>"
"<td class=\"DAT LEFT_MIDDLE\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],
2016-10-19 01:46:40 +02:00
Txt_Degree);
2016-10-19 20:43:26 +02:00
if (!PrintView &&
2017-06-04 18:18:54 +02:00
Gbl.Usrs.Me.Role.Logged >= Rol_CTR_ADM)
2016-10-23 14:49:03 +02:00
// Only centre admins, institution admins and system admin can move a course to another degree
2016-10-19 01:46:40 +02:00
{
2016-10-20 00:57:00 +02:00
/* Get list of degrees of the current centre */
Deg_GetListDegsOfCurrentCtr ();
/* Put form to select degree */
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActChgCrsDegCfg);
2016-12-21 00:45:51 +01:00
fprintf (Gbl.F.Out,"<select id=\"OthDegCod\" name=\"OthDegCod\""
2016-10-20 16:49:42 +02:00
" class=\"INPUT_SHORT_NAME\""
2016-10-19 01:46:40 +02:00
" onchange=\"document.getElementById('%s').submit();\">",
Gbl.Form.Id);
for (NumDeg = 0;
2019-04-03 20:57:04 +02:00
NumDeg < Gbl.Hierarchy.Ctr.Degs.Num;
2016-10-19 01:46:40 +02:00
NumDeg++)
fprintf (Gbl.F.Out,"<option value=\"%ld\"%s>%s</option>",
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Ctr.Degs.Lst[NumDeg].DegCod,
Gbl.Hierarchy.Ctr.Degs.Lst[NumDeg].DegCod == Gbl.Hierarchy.Deg.DegCod ? " selected=\"selected\"" :
"",
Gbl.Hierarchy.Ctr.Degs.Lst[NumDeg].ShrtName);
2016-10-19 01:46:40 +02:00
fprintf (Gbl.F.Out,"</select>");
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-10-19 01:55:50 +02:00
2016-10-20 00:57:00 +02:00
/* Free list of degrees of the current centre */
2019-04-03 20:57:04 +02:00
Deg_FreeListDegs (&Gbl.Hierarchy.Ctr.Degs);
2016-10-19 01:46:40 +02:00
}
2016-10-19 20:43:26 +02:00
else // I can not move course to another degree
2019-04-03 20:57:04 +02:00
fprintf (Gbl.F.Out,"%s",Gbl.Hierarchy.Deg.FullName);
2016-10-19 01:46:40 +02:00
fprintf (Gbl.F.Out,"</td>"
"</tr>");
2014-12-01 23:55:08 +01:00
/***** Course full name *****/
fprintf (Gbl.F.Out,"<tr>"
2016-12-21 00:45:51 +01:00
"<td class=\"RIGHT_MIDDLE\">"
"<label for=\"FullName\" class=\"%s\">%s:</label>"
2016-10-23 17:20:06 +02:00
"</td>"
"<td class=\"DAT_N LEFT_MIDDLE\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],
2016-10-23 17:20:06 +02:00
Txt_Course);
if (!PrintView &&
2017-06-04 18:18:54 +02:00
Gbl.Usrs.Me.Role.Logged >= Rol_DEG_ADM)
2016-10-23 17:20:06 +02:00
// Only degree admins, centre admins, institution admins and system admins can edit course full name
{
/* Form to change course full name */
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActRenCrsFulCfg);
2016-12-21 00:45:51 +01:00
fprintf (Gbl.F.Out,"<input type=\"text\""
" id=\"FullName\" name=\"FullName\""
2016-10-23 17:20:06 +02:00
" maxlength=\"%u\" value=\"%s\""
" class=\"INPUT_FULL_NAME\""
" onchange=\"document.getElementById('%s').submit();\" />",
2017-03-08 14:12:33 +01:00
Hie_MAX_CHARS_FULL_NAME,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.FullName,
2016-10-23 17:20:06 +02:00
Gbl.Form.Id);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-10-23 17:20:06 +02:00
}
else // I can not edit course full name
2019-04-04 10:45:15 +02:00
fprintf (Gbl.F.Out,"%s",Gbl.Hierarchy.Crs.FullName);
2016-10-23 17:20:06 +02:00
fprintf (Gbl.F.Out,"</td>"
"</tr>");
2014-12-01 23:55:08 +01:00
/***** Course short name *****/
fprintf (Gbl.F.Out,"<tr>"
2016-12-21 00:45:51 +01:00
"<td class=\"RIGHT_MIDDLE\">"
"<label for=\"ShortName\" class=\"%s\">%s:</label>"
2016-10-23 18:23:37 +02:00
"</td>"
"<td class=\"DAT_N LEFT_MIDDLE\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],
2016-10-23 18:23:37 +02:00
Txt_Short_name);
if (!PrintView &&
2017-06-04 18:18:54 +02:00
Gbl.Usrs.Me.Role.Logged >= Rol_DEG_ADM)
2016-10-23 18:23:37 +02:00
// Only degree admins, centre admins, institution admins and system admins can edit course short name
{
/* Form to change course short name */
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActRenCrsShoCfg);
2016-12-21 00:45:51 +01:00
fprintf (Gbl.F.Out,"<input type=\"text\""
" id=\"ShortName\" name=\"ShortName\""
2016-10-23 18:23:37 +02:00
" maxlength=\"%u\" value=\"%s\""
" class=\"INPUT_SHORT_NAME\""
" onchange=\"document.getElementById('%s').submit();\" />",
2017-03-08 14:12:33 +01:00
Hie_MAX_CHARS_SHRT_NAME,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.ShrtName,
2016-10-23 18:23:37 +02:00
Gbl.Form.Id);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-10-23 18:23:37 +02:00
}
else // I can not edit course short name
2019-04-04 10:45:15 +02:00
fprintf (Gbl.F.Out,"%s",Gbl.Hierarchy.Crs.ShrtName);
2016-10-23 18:23:37 +02:00
fprintf (Gbl.F.Out,"</td>"
"</tr>");
2014-12-01 23:55:08 +01:00
/***** Course year *****/
2019-04-03 20:57:04 +02:00
IsForm = (!PrintView && Gbl.Usrs.Me.Role.Logged >= Rol_TCH);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<tr>"
2016-12-21 00:45:51 +01:00
"<td class=\"RIGHT_MIDDLE\">"
"<label for=\"OthCrsYear\" class=\"%s\">%s:</label>"
2014-12-22 19:59:27 +01:00
"</td>"
2015-07-28 11:27:16 +02:00
"<td class=\"DAT LEFT_MIDDLE\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],
2014-12-01 23:55:08 +01:00
Txt_Year_OF_A_DEGREE);
if (IsForm)
{
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActChgCrsYeaCfg);
2016-12-21 00:45:51 +01:00
fprintf (Gbl.F.Out,"<select id=\"OthCrsYear\" name=\"OthCrsYear\""
2016-06-12 01:18:35 +02:00
" onchange=\"document.getElementById('%s').submit();\">",
Gbl.Form.Id);
2014-12-01 23:55:08 +01:00
for (Year = 0;
2016-02-29 18:53:26 +01:00
Year <= Deg_MAX_YEARS_PER_DEGREE;
2014-12-01 23:55:08 +01:00
Year++)
2016-02-29 18:53:26 +01:00
fprintf (Gbl.F.Out,"<option value=\"%u\"%s>%s</option>",
Year,
2019-04-04 10:45:15 +02:00
Year == Gbl.Hierarchy.Crs.Year ? " selected=\"selected\"" :
2016-02-29 18:53:26 +01:00
"",
Txt_YEAR_OF_DEGREE[Year]);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</select>");
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
}
else
2015-12-06 14:18:07 +01:00
fprintf (Gbl.F.Out,"%s",
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.Year ? Txt_YEAR_OF_DEGREE[Gbl.Hierarchy.Crs.Year] :
2015-12-06 14:18:07 +01:00
Txt_Not_applicable);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</td>"
"</tr>");
if (!PrintView)
{
/***** Institutional code of the course *****/
fprintf (Gbl.F.Out,"<tr>"
2016-12-21 00:45:51 +01:00
"<td class=\"RIGHT_MIDDLE\">"
"<label for=\"InsCrsCod\" class=\"%s\">%s:</label>"
2014-12-22 19:59:27 +01:00
"</td>"
2015-07-28 11:27:16 +02:00
"<td class=\"DAT LEFT_MIDDLE\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],
2014-12-01 23:55:08 +01:00
Txt_Institutional_code);
if (IsForm)
2016-06-12 01:18:35 +02:00
{
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActChgInsCrsCodCfg);
2016-12-21 00:45:51 +01:00
fprintf (Gbl.F.Out,"<input type=\"text\""
" id=\"InsCrsCod\" name=\"InsCrsCod\""
2016-06-12 01:18:35 +02:00
" size=\"%u\" maxlength=\"%u\" value=\"%s\""
" onchange=\"document.getElementById('%s').submit();\" />",
2017-03-07 11:03:05 +01:00
Crs_MAX_CHARS_INSTITUTIONAL_CRS_COD,
Crs_MAX_CHARS_INSTITUTIONAL_CRS_COD,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.InstitutionalCrsCod,
2016-06-12 01:18:35 +02:00
Gbl.Form.Id);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-06-12 01:18:35 +02:00
}
2014-12-01 23:55:08 +01:00
else
2019-04-04 10:45:15 +02:00
fprintf (Gbl.F.Out,"%s",Gbl.Hierarchy.Crs.InstitutionalCrsCod);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</td>"
"</tr>");
/***** Internal code of the course *****/
fprintf (Gbl.F.Out,"<tr>"
2015-07-27 21:25:45 +02:00
"<td class=\"%s RIGHT_MIDDLE\">"
2014-12-22 19:59:27 +01:00
"%s:"
"</td>"
2015-07-28 11:27:16 +02:00
"<td class=\"DAT LEFT_MIDDLE\">"
2014-12-22 19:59:27 +01:00
"%ld"
"</td>"
2014-12-01 23:55:08 +01:00
"</tr>",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],
2015-07-25 20:07:38 +02:00
Txt_Internal_code,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod);
2014-12-01 23:55:08 +01:00
}
/***** Link to the course *****/
fprintf (Gbl.F.Out,"<tr>"
2015-07-27 21:25:45 +02:00
"<td class=\"%s RIGHT_MIDDLE\">"
2014-12-22 19:59:27 +01:00
"%s:"
"</td>"
2015-07-28 11:27:16 +02:00
"<td class=\"DAT LEFT_MIDDLE\">"
2015-03-07 21:08:44 +01:00
"<a href=\"%s/%s?crs=%ld\" class=\"DAT\" target=\"_blank\">"
"%s/%s?crs=%ld</a>"
2014-12-01 23:55:08 +01:00
"</td>"
"</tr>",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],
2015-03-07 18:09:42 +01:00
Txt_Shortcut,
2016-07-08 12:43:48 +02:00
Cfg_URL_SWAD_CGI,
2018-12-08 16:43:13 +01:00
Lan_STR_LANG_ID[Gbl.Prefs.Language],
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod,
2016-07-08 12:43:48 +02:00
Cfg_URL_SWAD_CGI,
2018-12-08 16:43:13 +01:00
Lan_STR_LANG_ID[Gbl.Prefs.Language],
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod);
2014-12-01 23:55:08 +01:00
if (PrintView)
{
/***** QR code with link to the course *****/
fprintf (Gbl.F.Out,"<tr>"
2015-07-27 21:25:45 +02:00
"<td class=\"%s RIGHT_MIDDLE\">"
2014-12-22 19:59:27 +01:00
"%s:"
"</td>"
2015-07-28 11:27:16 +02:00
"<td class=\"DAT LEFT_MIDDLE\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],
2014-12-01 23:55:08 +01:00
Txt_QR_code);
2019-04-04 10:45:15 +02:00
QR_LinkTo (250,"crs",Gbl.Hierarchy.Crs.CrsCod);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</td>"
"</tr>");
}
else
{
2017-05-21 14:43:10 +02:00
/***** Number of users *****/
Crs_ShowNumUsrsInCrs (Rol_TCH);
2017-05-21 21:23:13 +02:00
Crs_ShowNumUsrsInCrs (Rol_NET);
2017-05-21 14:43:10 +02:00
Crs_ShowNumUsrsInCrs (Rol_STD);
2014-12-01 23:55:08 +01:00
/***** Indicators *****/
2019-04-04 10:45:15 +02:00
NumIndicatorsFromDB = Ind_GetNumIndicatorsCrsFromDB (Gbl.Hierarchy.Crs.CrsCod);
Ind_ComputeAndStoreIndicatorsCrs (Gbl.Hierarchy.Crs.CrsCod,
2016-06-10 10:22:22 +02:00
NumIndicatorsFromDB,&Indicators);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<tr>"
2015-07-27 21:25:45 +02:00
"<td class=\"%s RIGHT_MIDDLE\">"
2014-12-22 19:59:27 +01:00
"%s:"
"</td>"
2016-06-12 01:18:35 +02:00
"<td class=\"LEFT_MIDDLE\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],
2016-06-12 01:18:35 +02:00
Txt_Indicators);
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActReqStaCrs);
2018-10-17 10:32:18 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
"%u %s %u",
Indicators.NumIndicators,
Txt_of_PART_OF_A_TOTAL,Ind_NUM_INDICATORS);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Gbl.Title,"DAT",NULL);
2016-06-12 01:18:35 +02:00
fprintf (Gbl.F.Out,"%s "
2017-05-02 16:57:49 +02:00
"<img src=\"%s/%s\" alt=\"%s\""
2019-01-11 02:55:01 +01:00
" class=\"ICO16x16\" />",
2016-06-12 01:18:35 +02:00
Gbl.Title,
2019-03-20 01:36:36 +01:00
Cfg_URL_ICON_PUBLIC,
2019-01-11 02:55:01 +01:00
(Indicators.NumIndicators == Ind_NUM_INDICATORS) ? "check-circle.svg" :
"exclamation-triangle.svg",
2016-06-12 01:18:35 +02:00
Gbl.Title);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-06-12 01:18:35 +02:00
fprintf (Gbl.F.Out,"</td>"
"</tr>");
2014-12-08 17:35:48 +01:00
}
2014-12-01 23:55:08 +01:00
2016-03-18 19:23:30 +01:00
/***** End table *****/
2017-06-11 20:09:59 +02:00
Tbl_EndTable ();
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 ();
2016-03-18 19:23:30 +01:00
}
/*****************************************************************************/
/************* Put icon to print the configuration of a course ***************/
/*****************************************************************************/
static void Crs_PutIconToPrint (void)
{
2017-06-11 19:13:28 +02:00
Ico_PutContextualIconToPrint (ActPrnCrsInf,NULL);
2014-12-01 23:55:08 +01:00
}
2017-05-21 14:43:10 +02:00
/*****************************************************************************/
/**************** Number of users in courses of this country *****************/
/*****************************************************************************/
static void Crs_ShowNumUsrsInCrs (Rol_Role_t Role)
{
2019-02-22 21:47:50 +01:00
extern const char *The_ClassFormInBox[The_NUM_THEMES];
2017-05-21 14:43:10 +02:00
extern const char *Txt_ROLES_PLURAL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"%s RIGHT_MIDDLE\">"
"%s:"
"</td>"
"<td class=\"DAT LEFT_MIDDLE\">"
"%u"
"</td>"
"</tr>",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],
2017-05-21 14:43:10 +02:00
Txt_ROLES_PLURAL_Abc[Role][Usr_SEX_UNKNOWN],
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.NumUsrs[Role]);
2017-05-21 14:43:10 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************************ Write menu with my courses *************************/
/*****************************************************************************/
2015-12-15 01:33:09 +01:00
#define Crs_MAX_BYTES_TXT_LINK 40
2014-12-29 22:41:43 +01:00
2014-12-01 23:55:08 +01:00
static void Crs_WriteListMyCoursesToSelectOne (void)
{
2016-11-13 13:23:09 +01:00
extern const char *Hlp_PROFILE_Courses;
2019-02-22 21:47:50 +01:00
extern const char *The_ClassFormInBox[The_NUM_THEMES];
extern const char *The_ClassFormInBoxBold[The_NUM_THEMES];
2014-12-01 23:55:08 +01:00
extern const char *Txt_My_courses;
2015-02-05 00:55:47 +01:00
extern const char *Txt_System;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Go_to_X;
2014-12-29 00:54:56 +01:00
struct Country Cty;
2016-10-28 10:03:37 +02:00
struct Instit Ins;
2014-12-29 00:54:56 +01:00
struct Centre Ctr;
2014-12-01 23:55:08 +01:00
struct Degree Deg;
struct Course Crs;
2017-01-13 01:51:23 +01:00
bool IsLastItemInLevel[1 + 5];
2014-12-29 20:22:46 +01:00
bool Highlight; // Highlight because degree, course, etc. is selected
2014-12-29 00:54:56 +01:00
MYSQL_RES *mysql_resCty;
MYSQL_RES *mysql_resIns;
MYSQL_RES *mysql_resCtr;
MYSQL_RES *mysql_resDeg;
MYSQL_RES *mysql_resCrs;
MYSQL_ROW row;
2016-04-16 15:05:18 +02:00
unsigned NumCty;
unsigned NumCtys;
unsigned NumIns;
unsigned NumInss;
unsigned NumCtr;
unsigned NumCtrs;
unsigned NumDeg;
unsigned NumDegs;
unsigned NumCrs;
unsigned NumCrss;
2017-03-07 01:56:41 +01:00
char ActTxt[Act_MAX_BYTES_ACTION_TXT + 1];
2017-01-13 01:51:23 +01:00
const char *ClassNormal;
2015-12-25 21:19:31 +01:00
char ClassHighlight[64];
2019-02-22 21:47:50 +01:00
ClassNormal = The_ClassFormInBox[Gbl.Prefs.Theme];
2018-10-17 10:32:18 +02:00
snprintf (ClassHighlight,sizeof (ClassHighlight),
"%s LIGHT_BLUE",
2019-02-22 21:47:50 +01:00
The_ClassFormInBoxBold[Gbl.Prefs.Theme]);
2014-12-29 00:54:56 +01:00
2017-06-12 14:16:33 +02:00
/***** Start box *****/
2018-10-09 13:08:41 +02:00
Box_StartBox (NULL,Txt_My_courses,Crs_PutIconToSearchCourses,
2017-06-12 15:03:29 +02:00
Hlp_PROFILE_Courses,Box_NOT_CLOSABLE);
2016-12-19 00:55:24 +01:00
fprintf (Gbl.F.Out,"<ul class=\"LIST_LEFT\">");
2014-12-29 20:22:46 +01:00
/***** Write link to platform *****/
2019-04-03 20:57:04 +02:00
Highlight = (Gbl.Hierarchy.Cty.CtyCod <= 0);
2015-12-25 21:19:31 +01:00
fprintf (Gbl.F.Out,"<li class=\"%s\" style=\"height:25px;\">",
Highlight ? ClassHighlight :
ClassNormal);
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActMyCrs);
2015-12-25 22:05:28 +01:00
Cty_PutParamCtyCod (-1L);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Txt_System,
2015-12-25 21:19:31 +01:00
Highlight ? ClassHighlight :
2016-07-01 17:13:41 +02:00
ClassNormal,NULL);
2019-01-09 01:41:54 +01:00
fprintf (Gbl.F.Out,"<img src=\"%s/sitemap.svg\""
2015-07-21 17:37:37 +02:00
" alt=\"%s\" title=\"%s\""
2019-01-12 03:00:59 +01:00
" class=\"ICO16x16\" />&nbsp;%s</a>",
2019-03-20 01:36:36 +01:00
Cfg_URL_ICON_PUBLIC,
2015-02-05 00:55:47 +01:00
Txt_System,
2015-12-25 21:19:31 +01:00
Txt_System,
2015-02-05 00:55:47 +01:00
Txt_System);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2015-03-13 00:16:02 +01:00
fprintf (Gbl.F.Out,"</li>");
2014-12-29 00:54:56 +01:00
/***** Get my countries *****/
NumCtys = Usr_GetCtysFromUsr (Gbl.Usrs.Me.UsrDat.UsrCod,&mysql_resCty);
for (NumCty = 0;
NumCty < NumCtys;
NumCty++)
2014-12-01 23:55:08 +01:00
{
2014-12-29 00:54:56 +01:00
/***** Get next institution *****/
row = mysql_fetch_row (mysql_resCty);
/***** Get data of this institution *****/
Cty.CtyCod = Str_ConvertStrCodToLongCod (row[0]);
2015-12-09 19:51:17 +01:00
if (!Cty_GetDataOfCountryByCod (&Cty,Cty_GET_BASIC_DATA))
2014-12-29 00:54:56 +01:00
Lay_ShowErrorAndExit ("Country not found.");
/***** Write link to country *****/
2019-04-03 20:57:04 +02:00
Highlight = (Gbl.Hierarchy.Ins.InsCod <= 0 &&
Gbl.Hierarchy.Cty.CtyCod == Cty.CtyCod);
2015-12-25 21:19:31 +01:00
fprintf (Gbl.F.Out,"<li class=\"%s\" style=\"height:25px;\">",
Highlight ? ClassHighlight :
ClassNormal);
2014-12-29 13:26:39 +01:00
IsLastItemInLevel[1] = (NumCty == NumCtys - 1);
Lay_IndentDependingOnLevel (1,IsLastItemInLevel);
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActMyCrs);
2014-12-29 00:54:56 +01:00
Cty_PutParamCtyCod (Cty.CtyCod);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Act_GetActionTextFromDB (Act_GetActCod (ActSeeCtyInf),ActTxt),
2015-12-25 21:19:31 +01:00
Highlight ? ClassHighlight :
2016-07-01 17:13:41 +02:00
ClassNormal,NULL);
2014-12-29 00:54:56 +01:00
/* Country map */
2019-03-20 01:36:36 +01:00
fprintf (Gbl.F.Out,"<img src=\"%s/%s/%s.png\""
2015-07-21 17:37:37 +02:00
" alt=\"%s\" title=\"%s\""
2019-01-12 03:00:59 +01:00
" class=\"ICO16x16\" />&nbsp;%s</a>",
2019-03-20 01:36:36 +01:00
Cfg_URL_ICON_COUNTRIES_PUBLIC,
2014-12-29 00:54:56 +01:00
Cty.Alpha2,
Cty.Alpha2,
Cty.Alpha2,
2015-12-25 21:19:31 +01:00
Cty.Name[Gbl.Prefs.Language],
Cty.Name[Gbl.Prefs.Language]);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2015-03-13 00:16:02 +01:00
fprintf (Gbl.F.Out,"</li>");
2014-12-29 00:54:56 +01:00
/***** Get my institutions in this country *****/
2014-12-29 20:22:46 +01:00
NumInss = (unsigned) Usr_GetInssFromUsr (Gbl.Usrs.Me.UsrDat.UsrCod,
Cty.CtyCod,&mysql_resIns);
2014-12-29 00:54:56 +01:00
for (NumIns = 0;
NumIns < NumInss;
NumIns++)
{
/***** Get next institution *****/
row = mysql_fetch_row (mysql_resIns);
/***** Get data of this institution *****/
Ins.InsCod = Str_ConvertStrCodToLongCod (row[0]);
2015-12-09 19:51:17 +01:00
if (!Ins_GetDataOfInstitutionByCod (&Ins,Ins_GET_BASIC_DATA))
2014-12-29 00:54:56 +01:00
Lay_ShowErrorAndExit ("Institution not found.");
/***** Write link to institution *****/
2019-04-03 20:57:04 +02:00
Highlight = (Gbl.Hierarchy.Ctr.CtrCod <= 0 &&
Gbl.Hierarchy.Ins.InsCod == Ins.InsCod);
2017-03-04 19:46:46 +01:00
fprintf (Gbl.F.Out,"<li class=\"MY_CRSS_LNK %s\" style=\"height:25px;\">",
2015-12-25 21:19:31 +01:00
Highlight ? ClassHighlight :
ClassNormal);
2014-12-29 13:26:39 +01:00
IsLastItemInLevel[2] = (NumIns == NumInss - 1);
Lay_IndentDependingOnLevel (2,IsLastItemInLevel);
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActMyCrs);
2014-12-29 00:54:56 +01:00
Ins_PutParamInsCod (Ins.InsCod);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Act_GetActionTextFromDB (Act_GetActCod (ActSeeInsInf),ActTxt),
2015-12-25 21:19:31 +01:00
Highlight ? ClassHighlight :
2016-07-01 17:13:41 +02:00
ClassNormal,NULL);
2019-04-03 20:57:04 +02:00
Log_DrawLogo (Hie_INS,Ins.InsCod,Ins.ShrtName,16,NULL,true);
2017-03-04 19:46:46 +01:00
fprintf (Gbl.F.Out,"&nbsp;%s</a>",Ins.FullName);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2015-03-13 00:16:02 +01:00
fprintf (Gbl.F.Out,"</li>");
2014-12-29 00:54:56 +01:00
/***** Get my centres in this institution *****/
2014-12-29 20:22:46 +01:00
NumCtrs = (unsigned) Usr_GetCtrsFromUsr (Gbl.Usrs.Me.UsrDat.UsrCod,
Ins.InsCod,&mysql_resCtr);
2014-12-29 00:54:56 +01:00
for (NumCtr = 0;
NumCtr < NumCtrs;
NumCtr++)
{
/***** Get next centre *****/
row = mysql_fetch_row (mysql_resCtr);
/***** Get data of this centre *****/
Ctr.CtrCod = Str_ConvertStrCodToLongCod (row[0]);
if (!Ctr_GetDataOfCentreByCod (&Ctr))
Lay_ShowErrorAndExit ("Centre not found.");
/***** Write link to centre *****/
2019-04-03 20:57:04 +02:00
Highlight = (Gbl.Hierarchy.Level == Hie_CTR &&
Gbl.Hierarchy.Ctr.CtrCod == Ctr.CtrCod);
2017-03-04 19:46:46 +01:00
fprintf (Gbl.F.Out,"<li class=\"MY_CRSS_LNK %s\" style=\"height:25px;\">",
2015-12-25 21:19:31 +01:00
Highlight ? ClassHighlight :
ClassNormal);
2014-12-29 13:26:39 +01:00
IsLastItemInLevel[3] = (NumCtr == NumCtrs - 1);
Lay_IndentDependingOnLevel (3,IsLastItemInLevel);
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActMyCrs);
2014-12-29 00:54:56 +01:00
Ctr_PutParamCtrCod (Ctr.CtrCod);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Act_GetActionTextFromDB (Act_GetActCod (ActSeeCtrInf),ActTxt),
2015-12-25 21:19:31 +01:00
Highlight ? ClassHighlight :
2016-07-01 17:13:41 +02:00
ClassNormal,NULL);
2019-04-03 20:57:04 +02:00
Log_DrawLogo (Hie_CTR,Ctr.CtrCod,Ctr.ShrtName,16,NULL,true);
2017-03-04 19:46:46 +01:00
fprintf (Gbl.F.Out,"&nbsp;%s</a>",Ctr.FullName);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2015-03-13 00:16:02 +01:00
fprintf (Gbl.F.Out,"</li>");
2014-12-29 00:54:56 +01:00
/***** Get my degrees in this centre *****/
2014-12-29 20:22:46 +01:00
NumDegs = (unsigned) Usr_GetDegsFromUsr (Gbl.Usrs.Me.UsrDat.UsrCod,
Ctr.CtrCod,&mysql_resDeg);
2014-12-29 00:54:56 +01:00
for (NumDeg = 0;
NumDeg < NumDegs;
NumDeg++)
{
/***** Get next degree *****/
row = mysql_fetch_row (mysql_resDeg);
/***** Get data of this degree *****/
Deg.DegCod = Str_ConvertStrCodToLongCod (row[0]);
if (!Deg_GetDataOfDegreeByCod (&Deg))
Lay_ShowErrorAndExit ("Degree not found.");
/***** Write link to degree *****/
2019-04-03 20:57:04 +02:00
Highlight = (Gbl.Hierarchy.Level == Hie_DEG &&
Gbl.Hierarchy.Deg.DegCod == Deg.DegCod);
2017-03-04 19:46:46 +01:00
fprintf (Gbl.F.Out,"<li class=\"MY_CRSS_LNK %s\" style=\"height:25px;\">",
2015-12-25 21:19:31 +01:00
Highlight ? ClassHighlight :
ClassNormal);
2014-12-29 13:26:39 +01:00
IsLastItemInLevel[4] = (NumDeg == NumDegs - 1);
Lay_IndentDependingOnLevel (4,IsLastItemInLevel);
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActMyCrs);
2014-12-29 00:54:56 +01:00
Deg_PutParamDegCod (Deg.DegCod);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Act_GetActionTextFromDB (Act_GetActCod (ActSeeDegInf),ActTxt),
2015-12-25 21:19:31 +01:00
Highlight ? ClassHighlight :
2016-07-01 17:13:41 +02:00
ClassNormal,NULL);
2019-04-03 20:57:04 +02:00
Log_DrawLogo (Hie_DEG,Deg.DegCod,Deg.ShrtName,16,NULL,true);
2017-03-04 19:46:46 +01:00
fprintf (Gbl.F.Out,"&nbsp;%s</a>",Deg.FullName);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2015-03-13 00:16:02 +01:00
fprintf (Gbl.F.Out,"</li>");
2014-12-29 00:54:56 +01:00
/***** Get my courses in this degree *****/
2014-12-29 20:22:46 +01:00
NumCrss = (unsigned) Usr_GetCrssFromUsr (Gbl.Usrs.Me.UsrDat.UsrCod,
Deg.DegCod,&mysql_resCrs);
2014-12-29 00:54:56 +01:00
for (NumCrs = 0;
NumCrs < NumCrss;
NumCrs++)
{
/***** Get next course *****/
row = mysql_fetch_row (mysql_resCrs);
/***** Get data of this course *****/
Crs.CrsCod = Str_ConvertStrCodToLongCod (row[0]);
if (!Crs_GetDataOfCourseByCod (&Crs))
Lay_ShowErrorAndExit ("Course not found.");
/***** Write link to course *****/
2019-04-03 20:57:04 +02:00
Highlight = (Gbl.Hierarchy.Level == Hie_CRS &&
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod == Crs.CrsCod);
2017-03-04 19:46:46 +01:00
fprintf (Gbl.F.Out,"<li class=\"MY_CRSS_LNK %s\" style=\"height:25px;\">",
2015-12-25 21:19:31 +01:00
Highlight ? ClassHighlight :
ClassNormal);
2014-12-29 13:26:39 +01:00
IsLastItemInLevel[5] = (NumCrs == NumCrss - 1);
Lay_IndentDependingOnLevel (5,IsLastItemInLevel);
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActMyCrs);
2014-12-29 00:54:56 +01:00
Crs_PutParamCrsCod (Crs.CrsCod);
2018-10-17 10:32:18 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Go_to_X,
Crs.ShrtName);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Gbl.Title,
2015-12-25 21:19:31 +01:00
Highlight ? ClassHighlight :
2016-07-01 17:13:41 +02:00
ClassNormal,NULL);
2019-01-11 02:55:01 +01:00
fprintf (Gbl.F.Out,"<img src=\"%s/list-ol.svg\""
2015-07-21 17:37:37 +02:00
" alt=\"%s\" title=\"%s\""
2019-01-11 02:55:01 +01:00
" class=\"ICO16x16\" />"
2017-03-04 19:46:46 +01:00
"&nbsp;%s"
"</a>",
2019-03-20 01:36:36 +01:00
Cfg_URL_ICON_PUBLIC,
2016-10-28 10:03:37 +02:00
Crs.ShrtName,
2017-03-04 19:46:46 +01:00
Crs.FullName,
2015-07-21 17:37:37 +02:00
Crs.FullName);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2017-05-29 13:20:48 +02:00
/***** Put link to register students *****/
2017-05-29 21:34:43 +02:00
Enr_PutButtonInlineToRegisterStds (Crs.CrsCod);
2017-05-29 13:20:48 +02:00
2014-12-29 20:22:46 +01:00
fprintf (Gbl.F.Out,"</li>");
2014-12-29 00:54:56 +01:00
}
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_resCrs);
}
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_resDeg);
}
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_resCtr);
}
2014-12-01 23:55:08 +01:00
2014-12-29 00:54:56 +01:00
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_resIns);
2014-12-01 23:55:08 +01:00
}
2014-12-29 00:54:56 +01:00
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_resCty);
2017-06-12 14:16:33 +02:00
/***** End box *****/
2016-12-19 00:55:24 +01:00
fprintf (Gbl.F.Out,"</ul>");
2017-06-10 21:38:10 +02:00
Box_EndBox ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Get total number of courses *************************/
/*****************************************************************************/
unsigned Crs_GetNumCrssTotal (void)
{
/***** Get total number of courses from database *****/
2018-11-04 20:51:38 +01:00
return (unsigned) DB_GetNumRowsTable ("courses");
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****************** Get number of courses in a country ***********************/
/*****************************************************************************/
unsigned Crs_GetNumCrssInCty (long CtyCod)
{
/***** Get number of courses in a country from database *****/
2018-11-03 13:13:11 +01:00
return
(unsigned) DB_QueryCOUNT ("can not get the number of courses in a country",
"SELECT COUNT(*)"
" FROM institutions,centres,degrees,courses"
" WHERE institutions.CtyCod=%ld"
" AND institutions.InsCod=centres.InsCod"
" AND centres.CtrCod=degrees.CtrCod"
" AND degrees.DegCod=courses.DegCod",
CtyCod);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/**************** Get number of courses in an institution ********************/
/*****************************************************************************/
unsigned Crs_GetNumCrssInIns (long InsCod)
{
/***** Get number of courses in a degree from database *****/
2018-11-03 13:13:11 +01:00
return
(unsigned) DB_QueryCOUNT ("can not get the number of courses"
" in an institution",
"SELECT COUNT(*) FROM centres,degrees,courses"
" WHERE centres.InsCod=%ld"
" AND centres.CtrCod=degrees.CtrCod"
" AND degrees.DegCod=courses.DegCod",
InsCod);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Get number of courses in a centre **********************/
/*****************************************************************************/
unsigned Crs_GetNumCrssInCtr (long CtrCod)
{
/***** Get number of courses in a degree from database *****/
2018-11-03 13:13:11 +01:00
return
(unsigned) DB_QueryCOUNT ("can not get the number of courses in a centre",
"SELECT COUNT(*) FROM degrees,courses"
" WHERE degrees.CtrCod=%ld"
" AND degrees.DegCod=courses.DegCod",
CtrCod);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Get number of courses in a degree **********************/
/*****************************************************************************/
unsigned Crs_GetNumCrssInDeg (long DegCod)
{
/***** Get number of courses in a degree from database *****/
2018-11-03 13:13:11 +01:00
return
(unsigned) DB_QueryCOUNT ("can not get the number of courses in a degree",
"SELECT COUNT(*) FROM courses"
" WHERE DegCod=%ld",
DegCod);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************* Get number of courses with users **********************/
/*****************************************************************************/
unsigned Crs_GetNumCrssWithUsrs (Rol_Role_t Role,const char *SubQuery)
{
/***** Get number of degrees with users from database *****/
2018-11-03 13:13:11 +01:00
return
(unsigned) DB_QueryCOUNT ("can not get number of courses with users",
"SELECT COUNT(DISTINCT courses.CrsCod)"
" FROM institutions,centres,degrees,courses,crs_usr"
" WHERE %sinstitutions.InsCod=centres.InsCod"
" AND centres.CtrCod=degrees.CtrCod"
" AND degrees.DegCod=courses.DegCod"
" AND courses.CrsCod=crs_usr.CrsCod"
" AND crs_usr.Role=%u",
SubQuery,(unsigned) Role);
2014-12-01 23:55:08 +01:00
}
2015-07-25 20:20:07 +02:00
/*****************************************************************************/
/*************************** Write selector of course ************************/
/*****************************************************************************/
void Crs_WriteSelectorOfCourse (void)
{
extern const char *Txt_Course;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumCrss;
unsigned NumCrs;
long CrsCod;
/***** Start form *****/
2018-11-09 20:47:39 +01:00
Frm_StartFormGoTo (ActSeeCrsInf);
2016-12-20 10:03:00 +01:00
fprintf (Gbl.F.Out,"<select id=\"crs\" name=\"crs\" style=\"width:175px;\"");
2019-04-03 20:57:04 +02:00
if (Gbl.Hierarchy.Deg.DegCod > 0)
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);
2015-07-25 20:20:07 +02:00
else
fprintf (Gbl.F.Out," disabled=\"disabled\"");
2019-04-03 20:57:04 +02:00
fprintf (Gbl.F.Out,">"
"<option value=\"\"");
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Crs.CrsCod < 0)
2015-07-25 20:20:07 +02:00
fprintf (Gbl.F.Out," selected=\"selected\"");
fprintf (Gbl.F.Out," disabled=\"disabled\">[%s]</option>",
Txt_Course);
2019-04-03 20:57:04 +02:00
if (Gbl.Hierarchy.Deg.DegCod > 0)
2015-07-25 20:20:07 +02:00
{
/***** Get courses belonging to the current degree from database *****/
2018-10-30 14:47:31 +01:00
NumCrss = (unsigned) DB_QuerySELECT (&mysql_res,"can not get courses"
" of a degree",
"SELECT CrsCod,ShortName FROM courses"
" WHERE DegCod=%ld"
" ORDER BY ShortName",
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Deg.DegCod);
2015-07-25 20:20:07 +02:00
/***** Get courses of this degree *****/
for (NumCrs = 0;
NumCrs < NumCrss;
NumCrs++)
{
/* Get next course */
row = mysql_fetch_row (mysql_res);
/* Get course code (row[0]) */
if ((CrsCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong course.");
/* Write option */
fprintf (Gbl.F.Out,"<option value=\"%ld\"",CrsCod);
2019-04-03 20:57:04 +02:00
if (Gbl.Hierarchy.Level == Hie_CRS && // Course selected
2019-04-04 10:45:15 +02:00
(CrsCod == Gbl.Hierarchy.Crs.CrsCod))
2015-07-25 20:20:07 +02:00
fprintf (Gbl.F.Out," selected=\"selected\"");
fprintf (Gbl.F.Out,">%s</option>",row[1]);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/***** End form *****/
fprintf (Gbl.F.Out,"</select>");
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2015-07-25 20:20:07 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************************** Show courses of a degree *************************/
/*****************************************************************************/
void Crs_ShowCrssOfCurrentDeg (void)
{
2019-04-03 20:57:04 +02:00
/***** Trivial check *****/
if (Gbl.Hierarchy.Deg.DegCod <= 0) // No degree selected
return;
/***** Get list of courses in this degree *****/
Crs_GetListCoursesInCurrentDegree (Crs_ALL_COURSES_EXCEPT_REMOVED);
2014-12-01 23:55:08 +01:00
2019-04-03 20:57:04 +02:00
/***** Write menu to select country, institution, centre and degree *****/
Hie_WriteMenuHierarchy ();
2014-12-01 23:55:08 +01:00
2019-04-03 20:57:04 +02:00
/***** Show list of courses *****/
Crs_ListCourses ();
2014-12-01 23:55:08 +01:00
2019-04-03 20:57:04 +02:00
/***** Free list of courses in this degree *****/
2019-04-07 12:17:10 +02:00
Crs_FreeListCoursesInCurrentDegree ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2016-04-16 15:05:18 +02:00
/*************** Create a list with courses in current degree ****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-04-03 20:57:04 +02:00
static void Crs_GetListCoursesInCurrentDegree (Crs_WhatCourses_t WhatCourses)
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2016-04-16 15:05:18 +02:00
unsigned NumCrss;
2014-12-01 23:55:08 +01:00
unsigned NumCrs;
struct Course *Crs;
/***** Get courses of a degree from database *****/
switch (WhatCourses)
{
case Crs_ACTIVE_COURSES:
2018-10-30 14:47:31 +01:00
NumCrss = (unsigned) DB_QuerySELECT (&mysql_res,"can not get courses"
" of a degree",
"SELECT CrsCod,DegCod,Year,InsCrsCod,Status,RequesterUsrCod,ShortName,FullName"
" FROM courses WHERE DegCod=%ld AND Status=0"
" ORDER BY Year,ShortName",
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Deg.DegCod);
2014-12-01 23:55:08 +01:00
break;
case Crs_ALL_COURSES_EXCEPT_REMOVED:
2018-10-30 14:47:31 +01:00
NumCrss = (unsigned) DB_QuerySELECT (&mysql_res,"can not get courses"
" of a degree",
"SELECT CrsCod,DegCod,Year,InsCrsCod,Status,RequesterUsrCod,ShortName,FullName"
" FROM courses WHERE DegCod=%ld AND (Status & %u)=0"
" ORDER BY Year,ShortName",
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Deg.DegCod,
2018-10-30 14:47:31 +01:00
(unsigned) Crs_STATUS_BIT_REMOVED);
2014-12-01 23:55:08 +01:00
break;
default:
break;
}
2016-04-16 15:05:18 +02:00
if (NumCrss) // Courses found...
2014-12-01 23:55:08 +01:00
{
/***** Create list with courses in degree *****/
2019-04-04 10:45:15 +02:00
if ((Gbl.Hierarchy.Deg.Crss.Lst = (struct Course *) calloc ((size_t) NumCrss,
2019-04-03 20:57:04 +02:00
sizeof (struct Course))) == NULL)
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ();
2014-12-01 23:55:08 +01:00
/***** Get the courses in degree *****/
for (NumCrs = 0;
2016-04-16 15:05:18 +02:00
NumCrs < NumCrss;
2014-12-01 23:55:08 +01:00
NumCrs++)
{
2019-04-04 10:45:15 +02:00
Crs = &(Gbl.Hierarchy.Deg.Crss.Lst[NumCrs]);
2014-12-01 23:55:08 +01:00
/* Get next course */
row = mysql_fetch_row (mysql_res);
Crs_GetDataOfCourseFromRow (Crs,row);
}
}
2016-04-16 15:05:18 +02:00
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Deg.Crss.Num = NumCrss;
2014-12-01 23:55:08 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/********************* Free list of courses in this degree *******************/
/*****************************************************************************/
2019-04-07 12:17:10 +02:00
void Crs_FreeListCoursesInCurrentDegree (void)
2014-12-01 23:55:08 +01:00
{
2019-04-07 12:17:10 +02:00
if (Gbl.Hierarchy.Deg.Crss.Lst)
2014-12-01 23:55:08 +01:00
{
/***** Free memory used by the list of courses in degree *****/
2019-04-07 12:17:10 +02:00
free ((void *) Gbl.Hierarchy.Deg.Crss.Lst);
Gbl.Hierarchy.Deg.Crss.Lst = NULL;
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/********************** Write selector of my coursess ************************/
/*****************************************************************************/
2018-10-09 17:56:18 +02:00
void Crs_WriteSelectorMyCoursesInBreadcrumb (void)
2014-12-01 23:55:08 +01:00
{
2015-12-26 18:58:35 +01:00
extern const char *Txt_Course;
2014-12-01 23:55:08 +01:00
unsigned NumMyCrs;
long CrsCod;
long DegCod;
long LastDegCod;
2017-03-08 14:12:33 +01:00
char CrsShortName[Hie_MAX_BYTES_SHRT_NAME + 1];
char DegShortName[Hie_MAX_BYTES_SHRT_NAME + 1];
2014-12-01 23:55:08 +01:00
/***** Fill the list with the courses I belong to, if not filled *****/
if (Gbl.Usrs.Me.Logged)
Usr_GetMyCourses ();
/***** Start form *****/
2018-11-09 20:47:39 +01:00
Frm_StartFormGoTo (Gbl.Usrs.Me.MyCrss.Num ? ActSeeCrsInf :
2019-02-15 13:39:37 +01:00
ActReqSch);
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** Start selector of courses *****/
2016-12-27 16:45:37 +01:00
fprintf (Gbl.F.Out,"<select id=\"my_courses\" name=\"crs\""
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
2015-12-28 01:39:58 +01:00
/***** Write an option when no course selected *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Crs.CrsCod <= 0) // No course selected
2016-11-20 18:43:38 +01:00
fprintf (Gbl.F.Out,"<option value=\"-1\""
" disabled=\"disabled\" selected=\"selected\">"
"%s"
"</option>",
Txt_Course);
2015-12-28 01:39:58 +01:00
2016-10-28 10:03:37 +02:00
if (Gbl.Usrs.Me.MyCrss.Num)
2014-12-01 23:55:08 +01:00
{
/***** Write an option for each of my courses *****/
for (NumMyCrs = 0, LastDegCod = -1L;
2016-10-28 10:03:37 +02:00
NumMyCrs < Gbl.Usrs.Me.MyCrss.Num;
2014-12-01 23:55:08 +01:00
NumMyCrs++)
{
2016-10-28 10:03:37 +02:00
CrsCod = Gbl.Usrs.Me.MyCrss.Crss[NumMyCrs].CrsCod;
DegCod = Gbl.Usrs.Me.MyCrss.Crss[NumMyCrs].DegCod;
2014-12-01 23:55:08 +01:00
Crs_GetShortNamesByCod (CrsCod,CrsShortName,DegShortName);
if (DegCod != LastDegCod)
{
2016-11-20 18:43:38 +01:00
if (LastDegCod > 0)
fprintf (Gbl.F.Out,"</optgroup>");
fprintf (Gbl.F.Out,"<optgroup label=\"%s\">",DegShortName);
2014-12-01 23:55:08 +01:00
LastDegCod = DegCod;
}
fprintf (Gbl.F.Out,"<option value=\"%ld\"",
2016-10-28 10:03:37 +02:00
Gbl.Usrs.Me.MyCrss.Crss[NumMyCrs].CrsCod);
2019-04-04 10:45:15 +02:00
if (CrsCod == Gbl.Hierarchy.Crs.CrsCod) // Course selected
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out," selected=\"selected\"");
fprintf (Gbl.F.Out,">%s</option>",CrsShortName);
}
2016-11-20 18:43:38 +01:00
if (LastDegCod > 0)
fprintf (Gbl.F.Out,"</optgroup>");
2014-12-01 23:55:08 +01:00
}
2016-11-20 18:43:38 +01:00
/***** Write an option with the current course
when I don't belong to it *****/
2019-04-03 20:57:04 +02:00
if (Gbl.Hierarchy.Level == Hie_CRS && // Course selected
2016-11-20 18:43:38 +01:00
!Gbl.Usrs.Me.IBelongToCurrentCrs) // I do not belong to it
fprintf (Gbl.F.Out,"<option value=\"%ld\""
" disabled=\"disabled\" selected=\"selected\">"
"%s"
"</option>",
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Hierarchy.Crs.ShrtName);
2016-11-20 18:43:38 +01:00
2014-12-01 23:55:08 +01:00
/***** End form *****/
2015-03-13 00:16:02 +01:00
fprintf (Gbl.F.Out,"</select>");
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************* List courses in this degree ***********************/
/*****************************************************************************/
static void Crs_ListCourses (void)
{
2016-11-13 15:06:49 +01:00
extern const char *Hlp_DEGREE_Courses;
2016-03-20 12:35:27 +01:00
extern const char *Txt_Courses_of_DEGREE_X;
2016-03-20 13:18:56 +01:00
extern const char *Txt_No_courses;
2016-03-16 13:23:10 +01:00
extern const char *Txt_Create_another_course;
2015-10-06 01:19:21 +02:00
extern const char *Txt_Create_course;
2016-03-20 12:35:27 +01:00
unsigned Year;
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** Start box *****/
2018-10-17 10:32:18 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Courses_of_DEGREE_X,
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Deg.ShrtName);
2017-06-10 21:38:10 +02:00
Box_StartBox (NULL,Gbl.Title,Crs_PutIconsListCourses,
2017-06-12 15:03:29 +02:00
Hlp_DEGREE_Courses,Box_NOT_CLOSABLE);
2016-03-20 12:35:27 +01:00
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Deg.Crss.Num) // There are courses in the current degree
2016-03-20 12:35:27 +01:00
{
/***** Start table *****/
2017-06-11 20:09:59 +02:00
Tbl_StartTableWideMargin (2);
2016-03-20 12:35:27 +01:00
Crs_PutHeadCoursesForSeeing ();
/***** List the courses *****/
for (Year = 1;
Year <= Deg_MAX_YEARS_PER_DEGREE;
Year++)
if (Crs_ListCoursesOfAYearForSeeing (Year)) // If this year has courses ==>
Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd; // ==> change color for the next year
2016-06-04 13:07:33 +02:00
Crs_ListCoursesOfAYearForSeeing (0); // Courses without a year selected
2016-03-20 12:35:27 +01:00
/***** End table *****/
2017-06-11 20:09:59 +02:00
Tbl_EndTable ();
2016-03-20 12:35:27 +01:00
}
else // No courses created in the current degree
2019-02-16 14:37:34 +01:00
Ale_ShowAlert (Ale_INFO,Txt_No_courses);
2016-03-16 13:23:10 +01:00
2016-03-20 12:35:27 +01:00
/***** Button to create course *****/
2016-11-07 00:03:50 +01:00
if (Crs_CheckIfICanCreateCourses ())
2016-03-16 13:23:10 +01:00
{
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActEdiCrs);
2019-04-04 10:45:15 +02:00
Btn_PutConfirmButton (Gbl.Hierarchy.Deg.Crss.Num ? Txt_Create_another_course :
2019-04-03 20:57:04 +02:00
Txt_Create_course);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2015-10-06 01:19:21 +02:00
}
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 ();
2016-03-16 13:23:10 +01:00
}
2016-11-07 00:03:50 +01:00
/*****************************************************************************/
/********************** Check if I can create courses ************************/
/*****************************************************************************/
static bool Crs_CheckIfICanCreateCourses (void)
{
2017-06-04 18:18:54 +02:00
return (bool) (Gbl.Usrs.Me.Role.Logged >= Rol_GST);
2016-11-07 00:03:50 +01:00
}
/*****************************************************************************/
/***************** Put contextual icons in list of courses *******************/
/*****************************************************************************/
static void Crs_PutIconsListCourses (void)
{
/***** Put icon to edit courses *****/
if (Crs_CheckIfICanCreateCourses ())
Crs_PutIconToEditCourses ();
/***** Put icon to show a figure *****/
2019-02-12 14:46:14 +01:00
Gbl.Figures.FigureType = Fig_HIERARCHY;
Fig_PutIconToShowFigure ();
2016-11-07 00:03:50 +01:00
}
2016-03-16 13:23:10 +01:00
/*****************************************************************************/
2018-11-15 18:51:13 +01:00
/************************* Put icon to edit courses **************************/
2016-03-16 13:23:10 +01:00
/*****************************************************************************/
2016-03-16 22:40:35 +01:00
static void Crs_PutIconToEditCourses (void)
2016-03-16 13:23:10 +01:00
{
2017-06-11 19:13:28 +02:00
Ico_PutContextualIconToEdit (ActEdiCrs,NULL);
2014-12-01 23:55:08 +01:00
}
2015-12-06 14:18:07 +01:00
/*****************************************************************************/
/********************* List courses of a year for seeing *********************/
/*****************************************************************************/
// Return true if this year has courses
static bool Crs_ListCoursesOfAYearForSeeing (unsigned Year)
{
extern const char *Txt_COURSE_With_users;
extern const char *Txt_COURSE_Without_users;
2017-01-28 15:58:46 +01:00
extern const char *Txt_YEAR_OF_DEGREE[1 + Deg_MAX_YEARS_PER_DEGREE];
2015-12-06 14:18:07 +01:00
extern const char *Txt_Go_to_X;
extern const char *Txt_COURSE_STATUS[Crs_NUM_STATUS_TXT];
unsigned NumCrs;
struct Course *Crs;
const char *TxtClassNormal;
const char *TxtClassStrong;
const char *BgColor;
Crs_StatusTxt_t StatusTxt;
bool ThisYearHasCourses = false;
/***** Write all the courses of this year *****/
for (NumCrs = 0;
2019-04-04 10:45:15 +02:00
NumCrs < Gbl.Hierarchy.Deg.Crss.Num;
2015-12-06 14:18:07 +01:00
NumCrs++)
{
2019-04-04 10:45:15 +02:00
Crs = &(Gbl.Hierarchy.Deg.Crss.Lst[NumCrs]);
2015-12-06 14:18:07 +01:00
if (Crs->Year == Year) // The year of the course is this?
{
ThisYearHasCourses = true;
if (Crs->Status & Crs_STATUS_BIT_PENDING)
{
TxtClassNormal = "DAT_LIGHT";
TxtClassStrong = "DAT_LIGHT";
}
else
{
TxtClassNormal = "DAT";
TxtClassStrong = "DAT_N";
}
2018-10-04 22:45:16 +02:00
/* Check if this course is one of my courses */
BgColor = (Usr_CheckIfIBelongToCrs (Crs->CrsCod)) ? "LIGHT_BLUE" :
Gbl.ColorRows[Gbl.RowEvenOdd];
2015-12-06 14:18:07 +01:00
/* Put green tip if course has users */
fprintf (Gbl.F.Out,"<tr>"
2019-01-11 03:45:13 +01:00
"<td class=\"%s CENTER_MIDDLE %s\" title=\"%s\">"
"%s"
2015-12-06 14:18:07 +01:00
"</td>",
2019-01-11 03:45:13 +01:00
TxtClassNormal,BgColor,
2017-05-21 14:43:10 +02:00
Crs->NumUsrs[Rol_UNK] ? Txt_COURSE_With_users :
Txt_COURSE_Without_users,
2019-01-11 03:45:13 +01:00
Crs->NumUsrs[Rol_UNK] ? "&check;" :
"&nbsp;");
2015-12-06 14:18:07 +01:00
/* Institutional code of the course */
fprintf (Gbl.F.Out,"<td class=\"%s CENTER_MIDDLE %s\">"
"%s"
"</td>",
TxtClassNormal,BgColor,
Crs->InstitutionalCrsCod);
/* Course year */
fprintf (Gbl.F.Out,"<td class=\"%s CENTER_MIDDLE %s\">"
"%s"
"</td>",
TxtClassNormal,BgColor,
Txt_YEAR_OF_DEGREE[Crs->Year]);
/* Course full name */
fprintf (Gbl.F.Out,"<td class=\"%s LEFT_MIDDLE %s\">",
TxtClassStrong,BgColor);
2018-11-09 20:47:39 +01:00
Frm_StartFormGoTo (ActSeeCrsInf);
2015-12-06 14:18:07 +01:00
Crs_PutParamCrsCod (Crs->CrsCod);
2018-10-17 10:32:18 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Go_to_X,
Crs->FullName);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Gbl.Title,TxtClassStrong,NULL);
2015-12-06 14:18:07 +01:00
fprintf (Gbl.F.Out,"%s</a>",
Crs->FullName);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2015-12-06 14:18:07 +01:00
fprintf (Gbl.F.Out,"</td>");
2015-12-14 16:44:14 +01:00
/* Current number of teachers in this course */
2015-12-06 14:18:07 +01:00
fprintf (Gbl.F.Out,"<td class=\"%s RIGHT_MIDDLE %s\">"
"%u"
"</td>",
2017-05-21 16:48:30 +02:00
TxtClassNormal,BgColor,
Crs->NumUsrs[Rol_TCH] +
2017-05-21 21:23:13 +02:00
Crs->NumUsrs[Rol_NET]);
2015-12-06 14:18:07 +01:00
2015-12-14 16:44:14 +01:00
/* Current number of students in this course */
2015-12-06 14:18:07 +01:00
fprintf (Gbl.F.Out,"<td class=\"%s RIGHT_MIDDLE %s\">"
"%u"
"</td>",
2017-05-21 16:48:30 +02:00
TxtClassNormal,BgColor,
Crs->NumUsrs[Rol_STD]);
2015-12-06 14:18:07 +01:00
/* Course status */
StatusTxt = Crs_GetStatusTxtFromStatusBits (Crs->Status);
2017-03-17 00:46:28 +01:00
fprintf (Gbl.F.Out,"<td class=\"%s LEFT_MIDDLE %s\">",
TxtClassNormal,BgColor);
if (StatusTxt != Crs_STATUS_ACTIVE) // If active ==> do not show anything
fprintf (Gbl.F.Out,"%s",Txt_COURSE_STATUS[StatusTxt]);
fprintf (Gbl.F.Out,"</td>"
"</tr>");
2015-12-06 14:18:07 +01:00
}
}
return ThisYearHasCourses;
}
2016-03-20 12:35:27 +01:00
/*****************************************************************************/
/****************** Put forms to edit courses in this degree *****************/
/*****************************************************************************/
2017-04-30 12:44:53 +02:00
void Crs_EditCourses (void)
2019-04-07 19:49:53 +02:00
{
/***** Course constructor *****/
Crs_EditingCourseConstructor ();
/***** Edit courses *****/
Crs_EditCoursesInternal ();
/***** Course destructor *****/
Crs_EditingCourseDestructor ();
}
static void Crs_EditCoursesInternal (void)
2016-03-20 12:35:27 +01:00
{
2017-04-30 12:44:53 +02:00
extern const char *Hlp_DEGREE_Courses;
extern const char *Txt_Courses_of_DEGREE_X;
/***** Get list of degrees in this centre *****/
Deg_GetListDegsOfCurrentCtr ();
2019-04-07 12:17:10 +02:00
/***** Get list of courses in this degree *****/
Crs_GetListCoursesInCurrentDegree (Crs_ALL_COURSES_EXCEPT_REMOVED);
2018-11-15 18:51:13 +01:00
/***** Write menu to select country, institution, centre and degree *****/
Hie_WriteMenuHierarchy ();
2017-06-12 14:16:33 +02:00
/***** Start box *****/
2019-02-17 01:14:55 +01:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
2018-10-16 21:56:01 +02:00
Txt_Courses_of_DEGREE_X,
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Deg.ShrtName);
2019-02-17 01:14:55 +01:00
Box_StartBox (NULL,Gbl.Title,Crs_PutIconsEditingCourses,
2017-06-12 15:03:29 +02:00
Hlp_DEGREE_Courses,Box_NOT_CLOSABLE);
2017-04-30 12:44:53 +02:00
2016-03-20 12:35:27 +01:00
/***** Put a form to create or request a new course *****/
Crs_PutFormToCreateCourse ();
/***** Forms to edit current courses *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Deg.Crss.Num)
2016-03-20 12:35:27 +01:00
Crs_ListCoursesForEdition ();
2017-04-30 12:44:53 +02:00
2017-06-12 14:16:33 +02:00
/***** End box *****/
2017-06-10 21:38:10 +02:00
Box_EndBox ();
2017-04-30 12:44:53 +02:00
/***** Free list of courses in this degree *****/
2019-04-07 12:17:10 +02:00
Crs_FreeListCoursesInCurrentDegree ();
2017-04-30 12:44:53 +02:00
/***** Free list of degrees in this centre *****/
2019-04-03 20:57:04 +02:00
Deg_FreeListDegs (&Gbl.Hierarchy.Ctr.Degs);
2017-04-30 12:44:53 +02:00
}
/*****************************************************************************/
/**************** Put contextual icons in edition of courses *****************/
/*****************************************************************************/
2018-11-15 18:51:13 +01:00
static void Crs_PutIconsEditingCourses (void)
{
/***** Put icon to view degrees *****/
Crs_PutIconToViewCourses ();
/***** Put icon to show a figure *****/
2019-02-12 14:46:14 +01:00
Gbl.Figures.FigureType = Fig_HIERARCHY;
Fig_PutIconToShowFigure ();
2018-11-15 18:51:13 +01:00
}
/*****************************************************************************/
/************************* Put icon to view courses **************************/
/*****************************************************************************/
2017-04-30 12:44:53 +02:00
static void Crs_PutIconToViewCourses (void)
{
2018-11-15 18:51:13 +01:00
extern const char *Txt_Courses;
2019-01-12 03:00:59 +01:00
Lay_PutContextualLinkOnlyIcon (ActSeeCrs,NULL,NULL,
"list-ol.svg",
Txt_Courses);
2016-03-20 12:35:27 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/********************* List current courses for edition **********************/
/*****************************************************************************/
static void Crs_ListCoursesForEdition (void)
{
2016-07-04 09:54:36 +02:00
unsigned Year;
/***** Write heading *****/
2017-06-11 20:09:59 +02:00
Tbl_StartTableWide (2);
2016-07-04 09:54:36 +02:00
Crs_PutHeadCoursesForEdition ();
/***** List the courses *****/
for (Year = 1;
Year <= Deg_MAX_YEARS_PER_DEGREE;
Year++)
Crs_ListCoursesOfAYearForEdition (Year);
Crs_ListCoursesOfAYearForEdition (0);
/***** End table *****/
2017-06-11 20:09:59 +02:00
Tbl_EndTable ();
2016-07-04 09:54:36 +02:00
}
/*****************************************************************************/
/******************** List courses of a year for edition *********************/
/*****************************************************************************/
static void Crs_ListCoursesOfAYearForEdition (unsigned Year)
{
2017-01-28 15:58:46 +01:00
extern const char *Txt_YEAR_OF_DEGREE[1 + Deg_MAX_YEARS_PER_DEGREE];
2014-12-01 23:55:08 +01:00
extern const char *Txt_COURSE_STATUS[Crs_NUM_STATUS_TXT];
struct Course *Crs;
unsigned YearAux;
unsigned NumCrs;
struct UsrData UsrDat;
bool ICanEdit;
Crs_StatusTxt_t StatusTxt;
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
2016-07-04 09:54:36 +02:00
/***** List courses of a given year *****/
for (NumCrs = 0;
2019-04-04 10:45:15 +02:00
NumCrs < Gbl.Hierarchy.Deg.Crss.Num;
2016-07-04 09:54:36 +02:00
NumCrs++)
{
2019-04-04 10:45:15 +02:00
Crs = &(Gbl.Hierarchy.Deg.Crss.Lst[NumCrs]);
2016-07-04 09:54:36 +02:00
if (Crs->Year == Year)
{
ICanEdit = Crs_CheckIfICanEdit (Crs);
2014-12-01 23:55:08 +01:00
2016-07-04 09:54:36 +02:00
/* Put icon to remove course */
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"BM\">");
2017-05-21 14:43:10 +02:00
if (Crs->NumUsrs[Rol_UNK] || // Course has users ==> deletion forbidden
2016-07-04 09:54:36 +02:00
!ICanEdit)
2017-06-11 19:13:28 +02:00
Ico_PutIconRemovalNotAllowed ();
2016-07-04 09:54:36 +02:00
else // Crs->NumUsrs == 0 && ICanEdit
{
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActRemCrs);
2016-07-04 09:54:36 +02:00
Crs_PutParamOtherCrsCod (Crs->CrsCod);
2017-06-11 19:13:28 +02:00
Ico_PutIconRemove ();
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-07-04 09:54:36 +02:00
}
fprintf (Gbl.F.Out,"</td>");
2014-12-01 23:55:08 +01:00
2016-07-04 09:54:36 +02:00
/* Course code */
fprintf (Gbl.F.Out,"<td class=\"DAT CODE\">"
"%ld"
"</td>",
Crs->CrsCod);
2014-12-01 23:55:08 +01:00
2016-07-04 09:54:36 +02:00
/* Institutional code of the course */
fprintf (Gbl.F.Out,"<td class=\"DAT CENTER_MIDDLE\">");
if (ICanEdit)
{
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActChgInsCrsCod);
2016-07-04 09:54:36 +02:00
Crs_PutParamOtherCrsCod (Crs->CrsCod);
fprintf (Gbl.F.Out,"<input type=\"text\" name=\"InsCrsCod\""
" maxlength=\"%u\" value=\"%s\""
" class=\"INPUT_INS_CODE\""
" onchange=\"document.getElementById('%s').submit();\" />",
2017-03-07 11:03:05 +01:00
Crs_MAX_CHARS_INSTITUTIONAL_CRS_COD,
2016-07-04 09:54:36 +02:00
Crs->InstitutionalCrsCod,
Gbl.Form.Id);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-07-04 09:54:36 +02:00
}
else
fprintf (Gbl.F.Out,"%s",Crs->InstitutionalCrsCod);
fprintf (Gbl.F.Out,"</td>");
2014-12-01 23:55:08 +01:00
2016-07-04 09:54:36 +02:00
/* Course year */
fprintf (Gbl.F.Out,"<td class=\"DAT CENTER_MIDDLE\">");
if (ICanEdit)
{
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActChgCrsYea);
2016-07-04 09:54:36 +02:00
Crs_PutParamOtherCrsCod (Crs->CrsCod);
fprintf (Gbl.F.Out,"<select name=\"OthCrsYear\""
" style=\"width:50px;\""
" onchange=\"document.getElementById('%s').submit();\">",
Gbl.Form.Id);
for (YearAux = 0;
YearAux <= Deg_MAX_YEARS_PER_DEGREE;
YearAux++) // All the years are permitted because it's possible to move this course to another degree (with other active years)
fprintf (Gbl.F.Out,"<option value=\"%u\"%s>%s</option>",
YearAux,
YearAux == Crs->Year ? " selected=\"selected\"" :
"",
Txt_YEAR_OF_DEGREE[YearAux]);
fprintf (Gbl.F.Out,"</select>");
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-07-04 09:54:36 +02:00
}
else
fprintf (Gbl.F.Out,"%s",Txt_YEAR_OF_DEGREE[Crs->Year]);
fprintf (Gbl.F.Out,"</td>");
2014-12-01 23:55:08 +01:00
2016-07-04 09:54:36 +02:00
/* Course short name */
fprintf (Gbl.F.Out,"<td class=\"DAT LEFT_MIDDLE\">");
if (ICanEdit)
{
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActRenCrsSho);
2016-07-04 09:54:36 +02:00
Crs_PutParamOtherCrsCod (Crs->CrsCod);
fprintf (Gbl.F.Out,"<input type=\"text\" name=\"ShortName\""
" maxlength=\"%u\" value=\"%s\""
" class=\"INPUT_SHORT_NAME\""
" onchange=\"document.getElementById('%s').submit();\" />",
2017-03-08 14:12:33 +01:00
Hie_MAX_CHARS_SHRT_NAME,Crs->ShrtName,
2016-07-04 09:54:36 +02:00
Gbl.Form.Id);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-07-04 09:54:36 +02:00
}
else
2016-10-28 10:03:37 +02:00
fprintf (Gbl.F.Out,"%s",Crs->ShrtName);
2016-07-04 09:54:36 +02:00
fprintf (Gbl.F.Out,"</td>");
2014-12-01 23:55:08 +01:00
2016-07-04 09:54:36 +02:00
/* Course full name */
fprintf (Gbl.F.Out,"<td class=\"DAT LEFT_MIDDLE\">");
if (ICanEdit)
{
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActRenCrsFul);
2016-07-04 09:54:36 +02:00
Crs_PutParamOtherCrsCod (Crs->CrsCod);
fprintf (Gbl.F.Out,"<input type=\"text\" name=\"FullName\""
" maxlength=\"%u\" value=\"%s\""
" class=\"INPUT_FULL_NAME\""
" onchange=\"document.getElementById('%s').submit();\" />",
2017-03-08 14:12:33 +01:00
Hie_MAX_CHARS_FULL_NAME,Crs->FullName,
2016-07-04 09:54:36 +02:00
Gbl.Form.Id);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-07-04 09:54:36 +02:00
}
else
fprintf (Gbl.F.Out,"%s",Crs->FullName);
fprintf (Gbl.F.Out,"</td>");
2014-12-01 23:55:08 +01:00
2016-07-04 09:54:36 +02:00
/* Current number of teachers in this course */
fprintf (Gbl.F.Out,"<td class=\"DAT RIGHT_MIDDLE\">"
"%u"
"</td>",
2017-05-21 16:48:30 +02:00
Crs->NumUsrs[Rol_TCH] +
2017-05-21 21:23:13 +02:00
Crs->NumUsrs[Rol_NET]);
2016-07-04 09:54:36 +02:00
/* Current number of students in this course */
fprintf (Gbl.F.Out,"<td class=\"DAT RIGHT_MIDDLE\">"
"%u"
"</td>",
2017-05-21 14:43:10 +02:00
Crs->NumUsrs[Rol_STD]);
2016-07-04 09:54:36 +02:00
2017-03-17 00:46:28 +01:00
/* Course requester */
UsrDat.UsrCod = Crs->RequesterUsrCod;
2019-03-19 13:22:14 +01:00
Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat,Usr_DONT_GET_PREFS);
2017-05-02 01:05:23 +02:00
fprintf (Gbl.F.Out,"<td class=\"DAT INPUT_REQUESTER LEFT_TOP\">");
2017-05-02 01:16:06 +02:00
Msg_WriteMsgAuthor (&UsrDat,true,NULL);
2017-05-01 21:17:38 +02:00
fprintf (Gbl.F.Out,"</td>");
2017-03-17 00:46:28 +01:00
2016-07-04 09:54:36 +02:00
/* Course status */
StatusTxt = Crs_GetStatusTxtFromStatusBits (Crs->Status);
2017-03-17 00:46:28 +01:00
fprintf (Gbl.F.Out,"<td class=\"DAT LEFT_MIDDLE\">");
2017-06-04 18:18:54 +02:00
if (Gbl.Usrs.Me.Role.Logged >= Rol_DEG_ADM &&
2016-07-04 09:54:36 +02:00
StatusTxt == Crs_STATUS_PENDING)
{
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActChgCrsSta);
2016-07-04 09:54:36 +02:00
Crs_PutParamOtherCrsCod (Crs->CrsCod);
fprintf (Gbl.F.Out,"<select name=\"Status\" class=\"INPUT_STATUS\""
" onchange=\"document.getElementById('%s').submit();\">"
"<option value=\"%u\" selected=\"selected\">%s</option>"
"<option value=\"%u\">%s</option>"
"</select>",
Gbl.Form.Id,
(unsigned) Crs_GetStatusBitsFromStatusTxt (Crs_STATUS_PENDING),
Txt_COURSE_STATUS[Crs_STATUS_PENDING],
(unsigned) Crs_GetStatusBitsFromStatusTxt (Crs_STATUS_ACTIVE),
Txt_COURSE_STATUS[Crs_STATUS_ACTIVE]);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-07-04 09:54:36 +02:00
}
2017-03-17 00:46:28 +01:00
else if (StatusTxt != Crs_STATUS_ACTIVE) // If active ==> do not show anything
2016-07-04 09:54:36 +02:00
fprintf (Gbl.F.Out,"%s",Txt_COURSE_STATUS[StatusTxt]);
2017-03-17 00:46:28 +01:00
fprintf (Gbl.F.Out,"</td>"
2016-07-04 09:54:36 +02:00
"</tr>");
}
}
2014-12-01 23:55:08 +01:00
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
}
/*****************************************************************************/
/************** Check if I can edit, remove, etc. a course *******************/
/*****************************************************************************/
static bool Crs_CheckIfICanEdit (struct Course *Crs)
{
2017-06-04 18:18:54 +02:00
return (bool) (Gbl.Usrs.Me.Role.Logged >= Rol_DEG_ADM || // I am a degree administrator or higher
2014-12-01 23:55:08 +01:00
((Crs->Status & Crs_STATUS_BIT_PENDING) != 0 && // Course is not yet activated
Gbl.Usrs.Me.UsrDat.UsrCod == Crs->RequesterUsrCod)); // I am the requester
}
/*****************************************************************************/
/******************* Set StatusTxt depending on status bits ******************/
/*****************************************************************************/
// Crs_STATUS_UNKNOWN = 0 // Other
// Crs_STATUS_ACTIVE = 1 // 00 (Status == 0)
// Crs_STATUS_PENDING = 2 // 01 (Status == Crs_STATUS_BIT_PENDING)
// Crs_STATUS_REMOVED = 3 // 1- (Status & Crs_STATUS_BIT_REMOVED)
static Crs_StatusTxt_t Crs_GetStatusTxtFromStatusBits (Crs_Status_t Status)
{
if (Status == 0)
return Crs_STATUS_ACTIVE;
if (Status == Crs_STATUS_BIT_PENDING)
return Crs_STATUS_PENDING;
if (Status & Crs_STATUS_BIT_REMOVED)
return Crs_STATUS_REMOVED;
return Crs_STATUS_UNKNOWN;
}
/*****************************************************************************/
/******************* Set status bits depending on StatusTxt ******************/
/*****************************************************************************/
// Crs_STATUS_UNKNOWN = 0 // Other
// Crs_STATUS_ACTIVE = 1 // 00 (Status == 0)
// Crs_STATUS_PENDING = 2 // 01 (Status == Crs_STATUS_BIT_PENDING)
// Crs_STATUS_REMOVED = 3 // 1- (Status & Crs_STATUS_BIT_REMOVED)
static Crs_Status_t Crs_GetStatusBitsFromStatusTxt (Crs_StatusTxt_t StatusTxt)
{
switch (StatusTxt)
{
case Crs_STATUS_UNKNOWN:
case Crs_STATUS_ACTIVE:
return (Crs_Status_t) 0;
case Crs_STATUS_PENDING:
return Crs_STATUS_BIT_PENDING;
case Crs_STATUS_REMOVED:
return Crs_STATUS_BIT_REMOVED;
}
return (Crs_Status_t) 0;
}
/*****************************************************************************/
/*********************** Put a form to create a new course *******************/
/*****************************************************************************/
static void Crs_PutFormToCreateCourse (void)
{
2017-04-30 12:44:53 +02:00
extern const char *Txt_New_course;
2017-01-28 15:58:46 +01:00
extern const char *Txt_YEAR_OF_DEGREE[1 + Deg_MAX_YEARS_PER_DEGREE];
2014-12-01 23:55:08 +01:00
extern const char *Txt_Create_course;
unsigned Year;
/***** Start form *****/
2017-06-04 18:18:54 +02:00
if (Gbl.Usrs.Me.Role.Logged >= Rol_DEG_ADM)
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActNewCrs);
2017-06-04 18:18:54 +02:00
else if (Gbl.Usrs.Me.Role.Max >= Rol_GST)
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActReqCrs);
2014-12-01 23:55:08 +01:00
else
Lay_ShowErrorAndExit ("You can not edit courses.");
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_course,NULL,
2017-06-12 15:03:29 +02:00
NULL,Box_NOT_CLOSABLE,2);
2017-06-12 14:16:33 +02:00
/***** Write heading *****/
2014-12-01 23:55:08 +01:00
Crs_PutHeadCoursesForEdition ();
2017-04-30 14:03:45 +02:00
/***** Column to remove course, disabled here *****/
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<tr>"
2017-04-30 14:03:45 +02:00
"<td class=\"BM\"></td>");
2014-12-01 23:55:08 +01:00
/***** Course code *****/
2015-12-05 21:15:30 +01:00
fprintf (Gbl.F.Out,"<td class=\"CODE\"></td>");
2014-12-01 23:55:08 +01:00
/***** Institutional code of the course *****/
2015-07-28 11:27:16 +02:00
fprintf (Gbl.F.Out,"<td class=\"CENTER_MIDDLE\">"
2015-10-23 01:31:08 +02:00
"<input type=\"text\" name=\"InsCrsCod\""
2015-12-05 21:15:30 +01:00
" maxlength=\"%u\" value=\"%s\""
" class=\"INPUT_INS_CODE\" />"
2014-12-01 23:55:08 +01:00
"</td>",
2017-03-07 11:03:05 +01:00
Crs_MAX_CHARS_INSTITUTIONAL_CRS_COD,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->InstitutionalCrsCod);
2014-12-01 23:55:08 +01:00
/***** Year *****/
2015-07-28 11:27:16 +02:00
fprintf (Gbl.F.Out,"<td class=\"CENTER_MIDDLE\">"
2015-09-28 18:28:29 +02:00
"<select name=\"OthCrsYear\" style=\"width:50px;\">");
2014-12-01 23:55:08 +01:00
for (Year = 0;
2016-02-29 18:53:26 +01:00
Year <= Deg_MAX_YEARS_PER_DEGREE;
2014-12-01 23:55:08 +01:00
Year++)
2016-02-29 18:53:26 +01:00
fprintf (Gbl.F.Out,"<option value=\"%u\"%s>%s</option>",
Year,
2019-04-07 19:49:53 +02:00
Year == Crs_EditingCrs->Year ? " selected=\"selected\"" :
"",
2016-02-29 18:53:26 +01:00
Txt_YEAR_OF_DEGREE[Year]);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"</select>"
"</td>");
/***** Course short name *****/
2016-10-20 20:29:15 +02:00
fprintf (Gbl.F.Out,"<td class=\"LEFT_MIDDLE\">"
2015-10-23 01:31:08 +02:00
"<input type=\"text\" name=\"ShortName\""
2015-12-05 21:15:30 +01:00
" maxlength=\"%u\" value=\"%s\""
2016-11-19 02:57:47 +01:00
" class=\"INPUT_SHORT_NAME\""
" required=\"required\" />"
2014-12-01 23:55:08 +01:00
"</td>",
2019-04-07 19:49:53 +02:00
Hie_MAX_CHARS_SHRT_NAME,Crs_EditingCrs->ShrtName);
2014-12-01 23:55:08 +01:00
/***** Course full name *****/
2016-10-20 20:29:15 +02:00
fprintf (Gbl.F.Out,"<td class=\"LEFT_MIDDLE\">"
2015-10-23 01:31:08 +02:00
"<input type=\"text\" name=\"FullName\""
2015-12-05 21:15:30 +01:00
" maxlength=\"%u\" value=\"%s\""
2016-11-19 02:57:47 +01:00
" class=\"INPUT_FULL_NAME\""
" required=\"required\" />"
2014-12-01 23:55:08 +01:00
"</td>",
2019-04-07 19:49:53 +02:00
Hie_MAX_CHARS_FULL_NAME,Crs_EditingCrs->FullName);
2014-12-01 23:55:08 +01:00
2016-06-04 13:07:33 +02:00
/***** Current number of teachers in this course *****/
2015-07-28 11:27:16 +02:00
fprintf (Gbl.F.Out,"<td class=\"DAT RIGHT_MIDDLE\">"
2014-12-22 19:59:27 +01:00
"0"
"</td>");
2014-12-01 23:55:08 +01:00
2016-06-04 13:07:33 +02:00
/***** Current number of students in this course *****/
2015-07-28 11:27:16 +02:00
fprintf (Gbl.F.Out,"<td class=\"DAT RIGHT_MIDDLE\">"
2014-12-22 19:59:27 +01:00
"0"
"</td>");
2014-12-01 23:55:08 +01:00
/***** Course requester *****/
2017-05-02 01:05:23 +02:00
fprintf (Gbl.F.Out,"<td class=\"DAT INPUT_REQUESTER LEFT_TOP\">");
2017-05-02 01:16:06 +02:00
Msg_WriteMsgAuthor (&Gbl.Usrs.Me.UsrDat,true,NULL);
2017-05-01 21:17:38 +02:00
fprintf (Gbl.F.Out,"</td>");
2017-03-17 00:46:28 +01:00
/***** Course status *****/
fprintf (Gbl.F.Out,"<td class=\"DAT LEFT_MIDDLE\">"
"</td>"
2014-12-01 23:55:08 +01:00
"</tr>");
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_course);
2014-12-01 23:55:08 +01:00
2015-04-11 23:46:21 +02:00
/***** End form *****/
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Write header with fields of a course *******************/
/*****************************************************************************/
static void Crs_PutHeadCoursesForSeeing (void)
{
extern const char *Txt_Institutional_BR_code;
extern const char *Txt_Year_OF_A_DEGREE;
extern const char *Txt_Course;
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
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"
"</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=\"LEFT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_Institutional_BR_code,
Txt_Year_OF_A_DEGREE,
Txt_Course,
2017-05-30 21:43:05 +02:00
Txt_ROLES_PLURAL_BRIEF_Abc[Rol_TCH],
Txt_ROLES_PLURAL_BRIEF_Abc[Rol_STD]);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Write header with fields of a course *******************/
/*****************************************************************************/
static void Crs_PutHeadCoursesForEdition (void)
{
extern const char *Txt_Code;
2015-10-06 01:19:21 +02:00
extern const char *Txt_Institutional_code;
extern const char *Txt_optional;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Year_OF_A_DEGREE;
2016-03-02 20:29:31 +01:00
extern const char *Txt_Short_name_of_the_course;
extern const char *Txt_Full_name_of_the_course;
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_Requester;
fprintf (Gbl.F.Out,"<tr>"
"<th class=\"BM\"></th>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"CENTER_MIDDLE\">"
2015-10-06 01:19:21 +02:00
"%s (%s)"
2014-12-26 22:11:03 +01:00
"</th>"
2015-12-05 21:15:30 +01: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=\"LEFT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_Code,
2015-10-06 01:19:21 +02:00
Txt_Institutional_code,Txt_optional,
2014-12-01 23:55:08 +01:00
Txt_Year_OF_A_DEGREE,
2016-03-02 20:29:31 +01:00
Txt_Short_name_of_the_course,
Txt_Full_name_of_the_course,
2017-05-30 21:43:05 +02:00
Txt_ROLES_PLURAL_BRIEF_Abc[Rol_TCH],
Txt_ROLES_PLURAL_BRIEF_Abc[Rol_STD],
2014-12-01 23:55:08 +01:00
Txt_Requester);
}
/*****************************************************************************/
/****************** Receive form to request a new course *********************/
/*****************************************************************************/
void Crs_RecFormReqCrs (void)
{
2019-04-07 19:49:53 +02:00
/***** Course constructor *****/
Crs_EditingCourseConstructor ();
/***** Receive form to request a new course *****/
2014-12-01 23:55:08 +01:00
Crs_RecFormRequestOrCreateCrs ((unsigned) Crs_STATUS_BIT_PENDING);
}
/*****************************************************************************/
/******************* Receive form to create a new course *********************/
/*****************************************************************************/
void Crs_RecFormNewCrs (void)
{
2019-04-07 19:49:53 +02:00
/***** Course constructor *****/
Crs_EditingCourseConstructor ();
/***** Receive form to create a new course *****/
2014-12-01 23:55:08 +01:00
Crs_RecFormRequestOrCreateCrs (0);
}
/*****************************************************************************/
/************* Receive form to request or create a new course ****************/
/*****************************************************************************/
static void Crs_RecFormRequestOrCreateCrs (unsigned Status)
{
extern const char *Txt_The_course_X_already_exists;
2019-04-08 14:52:13 +02:00
extern const char *Txt_Created_new_course_X;
2014-12-01 23:55:08 +01:00
extern const char *Txt_You_must_specify_the_short_name_and_the_full_name_of_the_new_course;
2016-02-29 18:53:26 +01:00
extern const char *Txt_The_year_X_is_not_allowed;
2017-01-28 15:58:46 +01:00
extern const char *Txt_YEAR_OF_DEGREE[1 + Deg_MAX_YEARS_PER_DEGREE];
2014-12-01 23:55:08 +01:00
struct Degree Deg;
/***** Get parameters from form *****/
/* Set course degree */
2019-04-07 19:49:53 +02:00
Deg.DegCod = Crs_EditingCrs->DegCod = Gbl.Hierarchy.Deg.DegCod;
2014-12-01 23:55:08 +01:00
/* Get parameters of the new course */
2019-04-07 19:49:53 +02:00
Crs_GetParamsNewCourse (Crs_EditingCrs);
2014-12-01 23:55:08 +01:00
/***** Check if year is correct *****/
Deg_GetDataOfDegreeByCod (&Deg);
2019-04-07 19:49:53 +02:00
if (Crs_EditingCrs->Year <= Deg_MAX_YEARS_PER_DEGREE) // If year is valid
2014-12-01 23:55:08 +01:00
{
2019-04-07 19:49:53 +02:00
if (Crs_EditingCrs->ShrtName[0] &&
Crs_EditingCrs->FullName[0]) // If there's a course name
2014-12-01 23:55:08 +01:00
{
/***** If name of course was in database... *****/
2019-04-07 19:49:53 +02:00
if (Crs_CheckIfCrsNameExistsInYearOfDeg ("ShortName",Crs_EditingCrs->ShrtName,
-1L,Crs_EditingCrs->DegCod,Crs_EditingCrs->Year))
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_The_course_X_already_exists,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->ShrtName);
else if (Crs_CheckIfCrsNameExistsInYearOfDeg ("FullName",Crs_EditingCrs->FullName,
-1L,Crs_EditingCrs->DegCod,Crs_EditingCrs->Year))
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_The_course_X_already_exists,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->FullName);
2014-12-01 23:55:08 +01:00
else // Add new requested course to database
2019-04-08 14:52:13 +02:00
{
2017-05-11 20:04:38 +02:00
Crs_CreateCourse (Status);
2019-04-08 14:52:13 +02:00
Ale_CreateAlert (Ale_SUCCESS,NULL,
Txt_Created_new_course_X,
Crs_EditingCrs->FullName);
}
2014-12-01 23:55:08 +01:00
}
else // If there is not a course name
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_You_must_specify_the_short_name_and_the_full_name_of_the_new_course);
2014-12-01 23:55:08 +01:00
}
else // Year not valid
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_The_year_X_is_not_allowed,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->Year);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************** Get the parameters of a new course from form *****************/
/*****************************************************************************/
static void Crs_GetParamsNewCourse (struct Course *Crs)
{
2017-01-28 15:58:46 +01:00
char YearStr[2 + 1];
2014-12-01 23:55:08 +01:00
/***** Get parameters of the course from form *****/
/* Get institutional code */
2017-03-07 11:03:05 +01:00
Par_GetParToText ("InsCrsCod",Crs->InstitutionalCrsCod,Crs_MAX_BYTES_INSTITUTIONAL_CRS_COD);
2014-12-01 23:55:08 +01:00
/* Get year */
Par_GetParToText ("OthCrsYear",YearStr,2);
Crs->Year = Deg_ConvStrToYear (YearStr);
/* Get course short name */
2017-03-08 14:12:33 +01:00
Par_GetParToText ("ShortName",Crs->ShrtName,Hie_MAX_BYTES_SHRT_NAME);
2014-12-01 23:55:08 +01:00
/* Get course full name */
2017-03-08 14:12:33 +01:00
Par_GetParToText ("FullName",Crs->FullName,Hie_MAX_BYTES_FULL_NAME);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************* Add a new requested course to pending requests ****************/
/*****************************************************************************/
2017-05-11 20:04:38 +02:00
static void Crs_CreateCourse (unsigned Status)
2014-12-01 23:55:08 +01:00
{
/***** Insert new course into pending requests *****/
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->CrsCod =
2018-11-03 01:45:36 +01:00
DB_QueryINSERTandReturnCode ("can not create a new course",
"INSERT INTO courses"
" (DegCod,Year,InsCrsCod,Status,RequesterUsrCod,"
"ShortName,FullName)"
" VALUES"
" (%ld,%u,'%s',%u,%ld,"
"'%s','%s')",
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->DegCod,Crs_EditingCrs->Year,
Crs_EditingCrs->InstitutionalCrsCod,
2018-11-03 01:45:36 +01:00
Status,
Gbl.Usrs.Me.UsrDat.UsrCod,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->ShrtName,
Crs_EditingCrs->FullName);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2019-04-07 19:49:53 +02:00
/****************************** Remove a course ******************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Crs_RemoveCourse (void)
{
extern const char *Txt_To_remove_a_course_you_must_first_remove_all_users_in_the_course;
extern const char *Txt_Course_X_removed;
2019-04-07 19:49:53 +02:00
/***** Course constructor *****/
Crs_EditingCourseConstructor ();
2014-12-01 23:55:08 +01:00
/***** Get course code *****/
2019-04-08 12:21:16 +02:00
Crs_EditingCrs->CrsCod = Crs_GetAndCheckParamOtherCrsCod (1);
2014-12-01 23:55:08 +01:00
/***** Get data of the course from database *****/
2019-04-08 12:21:16 +02:00
Crs_GetDataOfCourseByCod (Crs_EditingCrs);
2014-12-01 23:55:08 +01:00
2019-04-08 12:21:16 +02:00
if (Crs_CheckIfICanEdit (Crs_EditingCrs))
2014-12-01 23:55:08 +01:00
{
/***** Check if this course has users *****/
2019-04-08 12:21:16 +02:00
if (Crs_EditingCrs->NumUsrs[Rol_UNK]) // Course has users ==> don't remove
2019-02-16 14:37:34 +01:00
Ale_ShowAlert (Ale_WARNING,Txt_To_remove_a_course_you_must_first_remove_all_users_in_the_course);
2017-05-21 14:43:10 +02:00
else // Course has no users ==> remove it
2014-12-01 23:55:08 +01:00
{
/***** Remove course *****/
2019-04-08 12:21:16 +02:00
Crs_RemoveCourseCompletely (Crs_EditingCrs->CrsCod);
2014-12-01 23:55:08 +01:00
/***** Write message to show the change made *****/
2019-02-16 14:37:34 +01:00
Ale_ShowAlert (Ale_SUCCESS,Txt_Course_X_removed,
2019-04-08 12:21:16 +02:00
Crs_EditingCrs->FullName);
2014-12-01 23:55:08 +01:00
}
}
else
2019-02-16 20:44:31 +01:00
Lay_NoPermissionExit ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********************* Get data of a course from its code ********************/
/*****************************************************************************/
bool Crs_GetDataOfCourseByCod (struct Course *Crs)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
bool CrsFound = false;
2016-12-30 01:20:49 +01:00
/***** Clear data *****/
2016-12-28 02:40:15 +01:00
Crs->DegCod = -1L;
Crs->Year = 0;
Crs->Status = (Crs_Status_t) 0;
Crs->RequesterUsrCod = -1L;
Crs->ShrtName[0] = '\0';
Crs->FullName[0] = '\0';
2017-05-29 13:20:48 +02:00
Crs->NumUsrs[Rol_UNK] =
Crs->NumUsrs[Rol_STD] =
2017-05-21 21:23:13 +02:00
Crs->NumUsrs[Rol_NET] =
2017-05-29 13:20:48 +02:00
Crs->NumUsrs[Rol_TCH] = 0;
2016-12-28 02:40:15 +01:00
2016-12-30 01:20:49 +01:00
/***** Check if course code is correct *****/
2016-12-28 02:40:15 +01:00
if (Crs->CrsCod > 0)
2014-12-01 23:55:08 +01:00
{
2016-12-28 02:40:15 +01:00
/***** Get data of a course from database *****/
2018-10-30 14:47:31 +01:00
if (DB_QuerySELECT (&mysql_res,"can not get data of a course",
"SELECT CrsCod,DegCod,Year,InsCrsCod,Status,RequesterUsrCod,ShortName,FullName"
" FROM courses WHERE CrsCod=%ld",
Crs->CrsCod)) // Course found...
2016-12-28 02:40:15 +01:00
{
/***** Get data of the course *****/
row = mysql_fetch_row (mysql_res);
Crs_GetDataOfCourseFromRow (Crs,row);
2014-12-01 23:55:08 +01:00
2016-12-30 01:20:49 +01:00
/* Set return value */
2016-12-28 02:40:15 +01:00
CrsFound = true;
}
2014-12-01 23:55:08 +01:00
2016-12-30 01:20:49 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
2014-12-01 23:55:08 +01:00
return CrsFound;
}
/*****************************************************************************/
/********** Get data of a course from a row resulting of a query *************/
/*****************************************************************************/
static void Crs_GetDataOfCourseFromRow (struct Course *Crs,MYSQL_ROW row)
{
/***** Get course code (row[0]) *****/
if ((Crs->CrsCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Wrong code of course.");
/***** Get code of degree (row[1]) *****/
Crs->DegCod = Str_ConvertStrCodToLongCod (row[1]);
/***** Get year (row[2]) *****/
Crs->Year = Deg_ConvStrToYear (row[2]);
2015-12-06 01:02:47 +01:00
/***** Get institutional course code (row[3]) *****/
2017-01-17 03:10:43 +01:00
Str_Copy (Crs->InstitutionalCrsCod,row[3],
2017-03-07 11:03:05 +01:00
Crs_MAX_BYTES_INSTITUTIONAL_CRS_COD);
2014-12-01 23:55:08 +01:00
2016-03-03 01:24:58 +01:00
/***** Get course status (row[4]) *****/
if (sscanf (row[4],"%u",&(Crs->Status)) != 1)
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ("Wrong course status.");
2016-03-03 01:24:58 +01:00
/***** Get requester user'code (row[5]) *****/
Crs->RequesterUsrCod = Str_ConvertStrCodToLongCod (row[5]);
2014-12-01 23:55:08 +01:00
2016-03-03 01:24:58 +01:00
/***** Get the short name of the course (row[6]) *****/
2017-01-17 03:10:43 +01:00
Str_Copy (Crs->ShrtName,row[6],
2017-03-08 14:12:33 +01:00
Hie_MAX_BYTES_SHRT_NAME);
2014-12-01 23:55:08 +01:00
2016-03-03 01:24:58 +01:00
/***** Get the full name of the course (row[7]) *****/
2017-01-17 03:10:43 +01:00
Str_Copy (Crs->FullName,row[7],
2017-03-08 14:12:33 +01:00
Hie_MAX_BYTES_FULL_NAME);
2014-12-01 23:55:08 +01:00
2017-05-21 16:48:30 +02:00
/***** Get number of users *****/
2017-05-29 13:20:48 +02:00
Crs->NumUsrs[Rol_STD] = Usr_GetNumUsrsInCrs (Rol_STD,Crs->CrsCod);
2017-05-21 21:23:13 +02:00
Crs->NumUsrs[Rol_NET] = Usr_GetNumUsrsInCrs (Rol_NET,Crs->CrsCod);
2017-05-29 13:20:48 +02:00
Crs->NumUsrs[Rol_TCH] = Usr_GetNumUsrsInCrs (Rol_TCH,Crs->CrsCod);
Crs->NumUsrs[Rol_UNK] = Crs->NumUsrs[Rol_STD] +
Crs->NumUsrs[Rol_NET] +
Crs->NumUsrs[Rol_TCH];
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******* Get the short names of degree and course from a course code *********/
/*****************************************************************************/
2017-01-13 01:51:23 +01:00
static void Crs_GetShortNamesByCod (long CrsCod,
2017-03-08 14:12:33 +01:00
char CrsShortName[Hie_MAX_BYTES_SHRT_NAME + 1],
char DegShortName[Hie_MAX_BYTES_SHRT_NAME + 1])
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
DegShortName[0] = CrsShortName[0] = '\0';
if (CrsCod > 0)
{
/***** Get the short name of a degree from database *****/
2018-10-30 14:47:31 +01:00
if (DB_QuerySELECT (&mysql_res,"can not get the short name of a course",
"SELECT courses.ShortName,degrees.ShortName"
" FROM courses,degrees"
" WHERE courses.CrsCod=%ld"
" AND courses.DegCod=degrees.DegCod",
CrsCod) == 1)
2014-12-01 23:55:08 +01:00
{
/***** Get the short name of this course *****/
row = mysql_fetch_row (mysql_res);
2017-01-13 01:51:23 +01:00
2017-01-17 03:10:43 +01:00
Str_Copy (CrsShortName,row[0],
2017-03-08 14:12:33 +01:00
Hie_MAX_BYTES_SHRT_NAME);
2017-01-17 03:10:43 +01:00
Str_Copy (DegShortName,row[1],
2017-03-08 14:12:33 +01:00
Hie_MAX_BYTES_SHRT_NAME);
2014-12-01 23:55:08 +01:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
}
/*****************************************************************************/
/****************************** Remove a course ******************************/
/*****************************************************************************/
void Crs_RemoveCourseCompletely (long CrsCod)
{
2017-05-31 21:05:59 +02:00
if (CrsCod > 0)
{
/***** Empty course *****/
Crs_EmptyCourseCompletely (CrsCod);
2014-12-01 23:55:08 +01:00
2017-05-31 21:05:59 +02:00
/***** Remove course from table of last accesses to courses in database *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove a course",
"DELETE FROM crs_last WHERE CrsCod=%ld",
CrsCod);
2014-12-01 23:55:08 +01:00
2017-05-31 21:05:59 +02:00
/***** Remove course from table of courses in database *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove a course",
"DELETE FROM courses WHERE CrsCod=%ld",
CrsCod);
2017-05-31 21:05:59 +02:00
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/********** Empty a course (remove all its information and users) ************/
/*****************************************************************************/
// Start removing less important things to more important things;
// so, in case of failure, important things can been removed in the future
static void Crs_EmptyCourseCompletely (long CrsCod)
{
struct Course Crs;
2017-01-28 15:58:46 +01:00
char PathRelCrs[PATH_MAX + 1];
2014-12-01 23:55:08 +01:00
2017-05-31 21:05:59 +02:00
if (CrsCod > 0)
{
/***** Get course data *****/
Crs.CrsCod = CrsCod;
Crs_GetDataOfCourseByCod (&Crs);
/***** Remove all the students in the course *****/
Enr_RemAllStdsInCrs (&Crs);
/***** Set all the notifications from the course as removed,
except notifications about new messages *****/
Ntf_MarkNotifInCrsAsRemoved (-1L,CrsCod);
/***** Remove information of the course ****/
/* Remove timetable of the course */
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove the timetable of a course",
"DELETE FROM timetable_crs WHERE CrsCod=%ld",
CrsCod);
2017-05-31 21:05:59 +02:00
/* Remove other information of the course */
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove info sources of a course",
"DELETE FROM crs_info_src WHERE CrsCod=%ld",
CrsCod);
2017-05-31 21:05:59 +02:00
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove info of a course",
"DELETE FROM crs_info_txt WHERE CrsCod=%ld",
CrsCod);
2017-05-31 21:05:59 +02:00
/***** Remove exam announcements in the course *****/
/* Mark all exam announcements in the course as deleted */
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ("can not remove exam announcements of a course",
"UPDATE exam_announcements SET Status=%u"
" WHERE CrsCod=%ld",
(unsigned) Exa_DELETED_EXAM_ANNOUNCEMENT,CrsCod);
2017-05-31 21:05:59 +02:00
/***** Remove course cards of the course *****/
/* Remove content of course cards */
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove content of cards in a course",
"DELETE FROM crs_records"
" USING crs_record_fields,crs_records"
" WHERE crs_record_fields.CrsCod=%ld"
" AND crs_record_fields.FieldCod=crs_records.FieldCod",
CrsCod);
2017-05-31 21:05:59 +02:00
/* Remove definition of fields in course cards */
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove fields of cards in a course",
"DELETE FROM crs_record_fields WHERE CrsCod=%ld",
CrsCod);
2017-05-31 21:05:59 +02:00
2017-10-08 02:56:40 +02:00
/***** Remove information related to files in course,
including groups and projects,
so this function must be called
before removing groups and projects *****/
Brw_RemoveCrsFilesFromDB (CrsCod);
2017-05-31 21:05:59 +02:00
/***** Remove assignments of the course *****/
Asg_RemoveCrsAssignments (CrsCod);
2014-12-01 23:55:08 +01:00
2017-09-24 22:35:18 +02:00
/***** Remove projects of the course *****/
Prj_RemoveCrsProjects (CrsCod);
2017-05-31 21:05:59 +02:00
/***** Remove attendance events of the course *****/
Att_RemoveCrsAttEvents (CrsCod);
/***** Remove notices in the course *****/
/* Copy all notices from the course to table of deleted notices */
2018-11-02 19:37:11 +01:00
DB_QueryINSERT ("can not remove notices in a course",
"INSERT INTO notices_deleted"
" (NotCod,CrsCod,UsrCod,CreatTime,Content,NumNotif)"
" SELECT NotCod,CrsCod,UsrCod,CreatTime,Content,NumNotif"
" FROM notices"
" WHERE CrsCod=%ld",
CrsCod);
2018-10-27 14:14:34 +02:00
2017-05-31 21:05:59 +02:00
/* Remove all notices from the course */
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove notices in a course",
"DELETE FROM notices WHERE CrsCod=%ld",
CrsCod);
2017-05-31 21:05:59 +02:00
/***** Remove all the threads and posts in forums of the course *****/
2019-04-03 20:57:04 +02:00
For_RemoveForums (Hie_CRS,CrsCod);
2017-05-31 21:05:59 +02:00
/***** Remove surveys of the course *****/
2019-04-03 20:57:04 +02:00
Svy_RemoveSurveys (Hie_CRS,CrsCod);
2017-05-31 21:05:59 +02:00
/***** Remove all test exams made in the course *****/
Tst_RemoveCrsTestResults (CrsCod);
/***** Remove all tests questions in the course *****/
Tst_RemoveCrsTests (CrsCod);
/***** Remove groups in the course *****/
/* Remove all the users in groups in the course */
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove users from groups of a course",
"DELETE FROM crs_grp_usr"
" USING crs_grp_types,crs_grp,crs_grp_usr"
" WHERE crs_grp_types.CrsCod=%ld"
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
" AND crs_grp.GrpCod=crs_grp_usr.GrpCod",
CrsCod);
2017-05-31 21:05:59 +02:00
/* Remove all the groups in the course */
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove groups of a course",
"DELETE FROM crs_grp"
" USING crs_grp_types,crs_grp"
" WHERE crs_grp_types.CrsCod=%ld"
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod",
CrsCod);
2017-05-31 21:05:59 +02:00
/* Remove all the group types in the course */
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove types of group of a course",
"DELETE FROM crs_grp_types WHERE CrsCod=%ld",
CrsCod);
2017-05-31 21:05:59 +02:00
/***** Remove users' requests for inscription in the course *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove requests for inscription to a course",
"DELETE FROM crs_usr_requests WHERE CrsCod=%ld",
CrsCod);
2017-05-31 21:05:59 +02:00
/***** Remove possible users remaining in the course (teachers) *****/
2018-11-02 22:00:31 +01:00
DB_QueryDELETE ("can not remove users from a course",
"DELETE FROM crs_usr WHERE CrsCod=%ld",
CrsCod);
2017-05-31 21:05:59 +02:00
/***** Remove directories of the course *****/
2018-10-17 10:32:18 +02:00
snprintf (PathRelCrs,sizeof (PathRelCrs),
2019-03-20 01:36:36 +01:00
"%s/%ld",
Cfg_PATH_CRS_PRIVATE,CrsCod);
2017-05-31 21:05:59 +02:00
Fil_RemoveTree (PathRelCrs);
2018-10-17 10:32:18 +02:00
snprintf (PathRelCrs,sizeof (PathRelCrs),
2019-03-20 01:36:36 +01:00
"%s/%ld",
Cfg_PATH_CRS_PUBLIC,CrsCod);
2017-05-31 21:05:59 +02:00
Fil_RemoveTree (PathRelCrs);
}
2014-12-01 23:55:08 +01:00
}
2016-06-12 01:18:35 +02:00
/*****************************************************************************/
/***** Change the institutional code of a course in course configuration *****/
/*****************************************************************************/
void Crs_ChangeInsCrsCodInConfig (void)
{
extern const char *Txt_The_institutional_code_of_the_course_X_has_changed_to_Y;
extern const char *Txt_The_institutional_code_of_the_course_X_has_not_changed;
2017-03-07 11:03:05 +01:00
char NewInstitutionalCrsCod[Crs_MAX_BYTES_INSTITUTIONAL_CRS_COD + 1];
2016-06-12 01:18:35 +02:00
/***** Get institutional code from form *****/
2017-03-07 11:03:05 +01:00
Par_GetParToText ("InsCrsCod",NewInstitutionalCrsCod,Crs_MAX_BYTES_INSTITUTIONAL_CRS_COD);
2016-06-12 01:18:35 +02:00
/***** Change the institutional course code *****/
2019-04-04 10:45:15 +02:00
if (strcmp (NewInstitutionalCrsCod,Gbl.Hierarchy.Crs.InstitutionalCrsCod))
2016-06-12 01:18:35 +02:00
{
2019-04-04 10:45:15 +02:00
Crs_UpdateInstitutionalCrsCod (&Gbl.Hierarchy.Crs,NewInstitutionalCrsCod);
2016-06-12 01:18:35 +02:00
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_SUCCESS,NULL,
Txt_The_institutional_code_of_the_course_X_has_changed_to_Y,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.ShrtName,
2019-03-09 20:12:44 +01:00
NewInstitutionalCrsCod);
2016-06-12 01:18:35 +02:00
}
else // The same institutional code
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_INFO,NULL,
Txt_The_institutional_code_of_the_course_X_has_not_changed,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.ShrtName);
2016-06-12 01:18:35 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************** Change the institutional code of a course ********************/
/*****************************************************************************/
void Crs_ChangeInsCrsCod (void)
{
extern const char *Txt_The_institutional_code_of_the_course_X_has_changed_to_Y;
extern const char *Txt_The_institutional_code_of_the_course_X_has_not_changed;
2017-03-07 11:03:05 +01:00
char NewInstitutionalCrsCod[Crs_MAX_BYTES_INSTITUTIONAL_CRS_COD + 1];
2014-12-01 23:55:08 +01:00
2019-04-07 19:49:53 +02:00
/***** Course constructor *****/
Crs_EditingCourseConstructor ();
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get course code */
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->CrsCod = Crs_GetAndCheckParamOtherCrsCod (1);
2014-12-01 23:55:08 +01:00
/* Get institutional code */
2017-03-07 11:03:05 +01:00
Par_GetParToText ("InsCrsCod",NewInstitutionalCrsCod,Crs_MAX_BYTES_INSTITUTIONAL_CRS_COD);
2014-12-01 23:55:08 +01:00
/* Get data of the course */
2019-04-07 19:49:53 +02:00
Crs_GetDataOfCourseByCod (Crs_EditingCrs);
2014-12-01 23:55:08 +01:00
2019-04-07 19:49:53 +02:00
if (Crs_CheckIfICanEdit (Crs_EditingCrs))
2014-12-01 23:55:08 +01:00
{
/***** Change the institutional course code *****/
2019-04-07 19:49:53 +02:00
if (strcmp (NewInstitutionalCrsCod,Crs_EditingCrs->InstitutionalCrsCod))
2014-12-01 23:55:08 +01:00
{
2019-04-07 19:49:53 +02:00
Crs_UpdateInstitutionalCrsCod (Crs_EditingCrs,NewInstitutionalCrsCod);
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_SUCCESS,NULL,
Txt_The_institutional_code_of_the_course_X_has_changed_to_Y,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->ShrtName,
2019-03-09 20:12:44 +01:00
NewInstitutionalCrsCod);
2014-12-01 23:55:08 +01:00
}
else // The same institutional code
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_INFO,NULL,
Txt_The_institutional_code_of_the_course_X_has_not_changed,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->ShrtName);
2014-12-01 23:55:08 +01:00
}
else
2019-02-16 20:44:31 +01:00
Lay_NoPermissionExit ();
2014-12-01 23:55:08 +01:00
}
2016-10-19 01:46:40 +02:00
/*****************************************************************************/
/***************** Change the degree of the current course *******************/
/*****************************************************************************/
2016-10-20 16:49:42 +02:00
void Crs_ChangeCrsDegInConfig (void)
2016-10-19 01:46:40 +02:00
{
extern const char *Txt_In_the_year_X_of_the_degree_Y_already_existed_a_course_with_the_name_Z;
2017-01-28 15:58:46 +01:00
extern const char *Txt_YEAR_OF_DEGREE[1 + Deg_MAX_YEARS_PER_DEGREE];
2016-10-19 01:46:40 +02:00
extern const char *Txt_The_course_X_has_been_moved_to_the_degree_Y;
struct Degree NewDeg;
2016-10-23 18:39:04 +02:00
/***** Get parameter with degree code *****/
2017-05-31 21:05:59 +02:00
NewDeg.DegCod = Deg_GetAndCheckParamOtherDegCod (1);
2016-10-19 20:43:26 +02:00
2016-10-20 20:02:59 +02:00
/***** Check if degree has changed *****/
2019-04-04 10:45:15 +02:00
if (NewDeg.DegCod != Gbl.Hierarchy.Crs.DegCod)
2016-10-19 01:46:40 +02:00
{
2016-10-20 20:02:59 +02:00
/***** Get data of new degree *****/
Deg_GetDataOfDegreeByCod (&NewDeg);
2016-10-19 01:46:40 +02:00
/***** If name of course was in database in the new degree... *****/
2019-04-04 10:45:15 +02:00
if (Crs_CheckIfCrsNameExistsInYearOfDeg ("ShortName",Gbl.Hierarchy.Crs.ShrtName,-1L,
NewDeg.DegCod,Gbl.Hierarchy.Crs.Year))
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_In_the_year_X_of_the_degree_Y_already_existed_a_course_with_the_name_Z,
2019-04-04 10:45:15 +02:00
Txt_YEAR_OF_DEGREE[Gbl.Hierarchy.Crs.Year],
2019-03-09 20:12:44 +01:00
NewDeg.FullName,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.ShrtName);
else if (Crs_CheckIfCrsNameExistsInYearOfDeg ("FullName",Gbl.Hierarchy.Crs.FullName,-1L,
NewDeg.DegCod,Gbl.Hierarchy.Crs.Year))
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_In_the_year_X_of_the_degree_Y_already_existed_a_course_with_the_name_Z,
2019-04-04 10:45:15 +02:00
Txt_YEAR_OF_DEGREE[Gbl.Hierarchy.Crs.Year],
2019-03-09 20:12:44 +01:00
NewDeg.FullName,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.FullName);
2016-10-19 01:46:40 +02:00
else // Update degree in database
{
/***** Update degree in table of courses *****/
2019-04-04 10:45:15 +02:00
Crs_UpdateCrsDegDB (Gbl.Hierarchy.Crs.CrsCod,NewDeg.DegCod);
Gbl.Hierarchy.Crs.DegCod =
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Deg.DegCod = NewDeg.DegCod;
2016-10-19 01:46:40 +02:00
/***** Initialize again current course, degree, centre... *****/
2016-11-14 17:26:32 +01:00
Hie_InitHierarchy ();
2016-10-19 01:46:40 +02:00
2019-03-09 20:12:44 +01:00
/***** Create alert to show the change made *****/
Ale_CreateAlert (Ale_SUCCESS,NULL,
Txt_The_course_X_has_been_moved_to_the_degree_Y,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.FullName,
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Deg.FullName);
2016-10-19 01:46:40 +02:00
}
}
}
2016-10-19 20:43:26 +02:00
/*****************************************************************************/
/** Show message of success after changing a course in course configuration **/
/*****************************************************************************/
void Crs_ContEditAfterChgCrsInConfig (void)
{
/***** Write error/success message *****/
2019-03-09 20:12:44 +01:00
Ale_ShowAlerts (NULL);
2016-10-19 20:43:26 +02:00
/***** Show the form again *****/
Crs_ShowIntroduction ();
}
2016-10-19 23:21:53 +02:00
/*****************************************************************************/
/********************** Update degree in table of courses ********************/
/*****************************************************************************/
2016-10-20 16:49:42 +02:00
static void Crs_UpdateCrsDegDB (long CrsCod,long DegCod)
2016-10-19 23:21:53 +02:00
{
/***** Update degree in table of courses *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ("can not move course to another degree",
"UPDATE courses SET DegCod=%ld WHERE CrsCod=%ld",
DegCod,CrsCod);
2016-10-19 23:21:53 +02:00
}
2016-06-12 01:18:35 +02:00
/*****************************************************************************/
/*********** Change the year of a course in course configuration *************/
/*****************************************************************************/
void Crs_ChangeCrsYearInConfig (void)
{
extern const char *Txt_The_course_X_already_exists_in_year_Y;
2017-01-28 15:58:46 +01:00
extern const char *Txt_YEAR_OF_DEGREE[1 + Deg_MAX_YEARS_PER_DEGREE];
2016-06-12 01:18:35 +02:00
extern const char *Txt_The_year_of_the_course_X_has_changed;
extern const char *Txt_The_year_X_is_not_allowed;
2017-01-28 15:58:46 +01:00
char YearStr[2 + 1];
2016-06-12 01:18:35 +02:00
unsigned NewYear;
/***** Get parameter with year/semester *****/
Par_GetParToText ("OthCrsYear",YearStr,2);
NewYear = Deg_ConvStrToYear (YearStr);
if (NewYear <= Deg_MAX_YEARS_PER_DEGREE) // If year is valid
{
/***** If name of course was in database in the new year... *****/
2019-04-04 10:45:15 +02:00
if (Crs_CheckIfCrsNameExistsInYearOfDeg ("ShortName",Gbl.Hierarchy.Crs.ShrtName,-1L,
Gbl.Hierarchy.Crs.DegCod,NewYear))
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_The_course_X_already_exists_in_year_Y,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.ShrtName,
2019-03-09 20:12:44 +01:00
Txt_YEAR_OF_DEGREE[NewYear]);
2019-04-04 10:45:15 +02:00
else if (Crs_CheckIfCrsNameExistsInYearOfDeg ("FullName",Gbl.Hierarchy.Crs.FullName,-1L,
Gbl.Hierarchy.Crs.DegCod,NewYear))
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_The_course_X_already_exists_in_year_Y,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.FullName,
2019-03-09 20:12:44 +01:00
Txt_YEAR_OF_DEGREE[NewYear]);
2016-06-12 01:18:35 +02:00
else // Update year in database
{
/***** Update year in table of courses *****/
2019-04-04 10:45:15 +02:00
Crs_UpdateCrsYear (&Gbl.Hierarchy.Crs,NewYear);
2016-06-12 01:18:35 +02:00
2019-03-09 20:12:44 +01:00
/***** Create alert to show the change made *****/
Ale_CreateAlert (Ale_SUCCESS,NULL,
Txt_The_year_of_the_course_X_has_changed,
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.ShrtName);
2016-06-12 01:18:35 +02:00
}
}
else // Year not valid
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_The_year_X_is_not_allowed,
NewYear);
2016-06-12 01:18:35 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************************ Change the year of a course ************************/
/*****************************************************************************/
void Crs_ChangeCrsYear (void)
{
extern const char *Txt_The_course_X_already_exists_in_year_Y;
2017-01-28 15:58:46 +01:00
extern const char *Txt_YEAR_OF_DEGREE[1 + Deg_MAX_YEARS_PER_DEGREE];
2014-12-01 23:55:08 +01:00
extern const char *Txt_The_year_of_the_course_X_has_changed;
2016-02-29 18:53:26 +01:00
extern const char *Txt_The_year_X_is_not_allowed;
2014-12-01 23:55:08 +01:00
struct Degree Deg;
2017-01-28 15:58:46 +01:00
char YearStr[2 + 1];
2014-12-01 23:55:08 +01:00
unsigned NewYear;
2019-04-07 19:49:53 +02:00
/***** Course constructor *****/
Crs_EditingCourseConstructor ();
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get course code */
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->CrsCod = Crs_GetAndCheckParamOtherCrsCod (1);
2014-12-01 23:55:08 +01:00
/* Get parameter with year */
Par_GetParToText ("OthCrsYear",YearStr,2);
NewYear = Deg_ConvStrToYear (YearStr);
2019-04-07 19:49:53 +02:00
Crs_GetDataOfCourseByCod (Crs_EditingCrs);
2014-12-01 23:55:08 +01:00
2019-04-07 19:49:53 +02:00
if (Crs_CheckIfICanEdit (Crs_EditingCrs))
2014-12-01 23:55:08 +01:00
{
2019-04-07 19:49:53 +02:00
Deg.DegCod = Crs_EditingCrs->DegCod;
2014-12-01 23:55:08 +01:00
Deg_GetDataOfDegreeByCod (&Deg);
2016-02-29 18:53:26 +01:00
if (NewYear <= Deg_MAX_YEARS_PER_DEGREE) // If year is valid
2014-12-01 23:55:08 +01:00
{
/***** If name of course was in database in the new year... *****/
2019-04-07 19:49:53 +02:00
if (Crs_CheckIfCrsNameExistsInYearOfDeg ("ShortName",Crs_EditingCrs->ShrtName,
-1L,Crs_EditingCrs->DegCod,NewYear))
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_The_course_X_already_exists_in_year_Y,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->ShrtName,
2019-03-09 20:12:44 +01:00
Txt_YEAR_OF_DEGREE[NewYear]);
2019-04-07 19:49:53 +02:00
else if (Crs_CheckIfCrsNameExistsInYearOfDeg ("FullName",Crs_EditingCrs->FullName,
-1L,Crs_EditingCrs->DegCod,NewYear))
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_The_course_X_already_exists_in_year_Y,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->FullName,
2019-03-09 20:12:44 +01:00
Txt_YEAR_OF_DEGREE[NewYear]);
2014-12-01 23:55:08 +01:00
else // Update year in database
{
/***** Update year in table of courses *****/
2019-04-07 19:49:53 +02:00
Crs_UpdateCrsYear (Crs_EditingCrs,NewYear);
2014-12-01 23:55:08 +01:00
2016-03-24 20:13:42 +01:00
/***** Create message to show the change made *****/
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_SUCCESS,NULL,
Txt_The_year_of_the_course_X_has_changed,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->ShrtName);
2014-12-01 23:55:08 +01:00
}
}
else // Year not valid
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_The_year_X_is_not_allowed,
NewYear);
2014-12-01 23:55:08 +01:00
}
else
2019-02-16 20:44:31 +01:00
Lay_NoPermissionExit ();
2014-12-01 23:55:08 +01:00
}
2016-06-12 01:18:35 +02:00
/*****************************************************************************/
/****************** Change the year/semester of a course *********************/
/*****************************************************************************/
static void Crs_UpdateCrsYear (struct Course *Crs,unsigned NewYear)
{
/***** Update year/semester in table of courses *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ("can not update the year of a course",
"UPDATE courses SET Year=%u WHERE CrsCod=%ld",
NewYear,Crs->CrsCod);
2016-06-12 01:18:35 +02:00
2016-07-02 11:26:08 +02:00
/***** Copy course year/semester *****/
2016-06-12 01:18:35 +02:00
Crs->Year = NewYear;
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-03-01 13:36:48 +01:00
/************* Change the institutional course code of a course **************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-03-01 13:36:48 +01:00
void Crs_UpdateInstitutionalCrsCod (struct Course *Crs,const char *NewInstitutionalCrsCod)
2014-12-01 23:55:08 +01:00
{
/***** Update institutional course code in table of courses *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ("can not update the institutional code"
" of the current course",
"UPDATE courses SET InsCrsCod='%s' WHERE CrsCod=%ld",
NewInstitutionalCrsCod,Crs->CrsCod);
2014-12-01 23:55:08 +01:00
/***** Copy institutional course code *****/
2017-01-15 18:02:52 +01:00
Str_Copy (Crs->InstitutionalCrsCod,NewInstitutionalCrsCod,
2017-03-07 11:03:05 +01:00
Crs_MAX_BYTES_INSTITUTIONAL_CRS_COD);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2019-04-07 19:49:53 +02:00
/************************ Change the name of a course ************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Crs_RenameCourseShort (void)
{
2019-04-07 19:49:53 +02:00
/***** Course constructor *****/
Crs_EditingCourseConstructor ();
/***** Rename course *****/
Crs_EditingCrs->CrsCod = Crs_GetAndCheckParamOtherCrsCod (1);
Crs_RenameCourse (Crs_EditingCrs,Cns_SHRT_NAME);
2014-12-01 23:55:08 +01:00
}
2019-04-07 19:49:53 +02:00
void Crs_RenameCourseFull (void)
2016-10-23 18:23:37 +02:00
{
2019-04-07 19:49:53 +02:00
/***** Course constructor *****/
Crs_EditingCourseConstructor ();
/***** Rename course *****/
Crs_EditingCrs->CrsCod = Crs_GetAndCheckParamOtherCrsCod (1);
Crs_RenameCourse (Crs_EditingCrs,Cns_FULL_NAME);
2016-10-23 18:23:37 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-04-07 19:49:53 +02:00
/*************** Change the name of a course in configuration ****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2019-04-07 19:49:53 +02:00
void Crs_RenameCourseShortInConfig (void)
2014-12-01 23:55:08 +01:00
{
2019-04-07 19:49:53 +02:00
Crs_RenameCourse (&Gbl.Hierarchy.Crs,Cns_SHRT_NAME);
2016-10-23 17:20:06 +02:00
}
2014-12-01 23:55:08 +01:00
2016-10-23 17:20:06 +02:00
void Crs_RenameCourseFullInConfig (void)
{
2019-04-04 10:45:15 +02:00
Crs_RenameCourse (&Gbl.Hierarchy.Crs,Cns_FULL_NAME);
2016-10-23 17:20:06 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************************ Change the name of a course ************************/
/*****************************************************************************/
2016-10-28 10:03:37 +02:00
static void Crs_RenameCourse (struct Course *Crs,Cns_ShrtOrFullName_t ShrtOrFullName)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_You_can_not_leave_the_name_of_the_course_X_empty;
extern const char *Txt_The_course_X_already_exists;
extern const char *Txt_The_name_of_the_course_X_has_changed_to_Y;
extern const char *Txt_The_name_of_the_course_X_has_not_changed;
const char *ParamName = NULL; // Initialized to avoid warning
const char *FieldName = NULL; // Initialized to avoid warning
2017-03-07 11:03:05 +01:00
unsigned MaxBytes = 0; // Initialized to avoid warning
2014-12-01 23:55:08 +01:00
char *CurrentCrsName = NULL; // Initialized to avoid warning
2017-03-08 14:12:33 +01:00
char NewCrsName[Hie_MAX_BYTES_FULL_NAME + 1];
2014-12-01 23:55:08 +01:00
2016-10-28 10:03:37 +02:00
switch (ShrtOrFullName)
2014-12-01 23:55:08 +01:00
{
2016-10-28 10:03:37 +02:00
case Cns_SHRT_NAME:
2014-12-01 23:55:08 +01:00
ParamName = "ShortName";
FieldName = "ShortName";
2017-03-08 14:12:33 +01:00
MaxBytes = Hie_MAX_BYTES_SHRT_NAME;
2016-10-28 10:03:37 +02:00
CurrentCrsName = Crs->ShrtName;
2014-12-01 23:55:08 +01:00
break;
case Cns_FULL_NAME:
ParamName = "FullName";
FieldName = "FullName";
2017-03-08 14:12:33 +01:00
MaxBytes = Hie_MAX_BYTES_FULL_NAME;
2014-12-01 23:55:08 +01:00
CurrentCrsName = Crs->FullName;
break;
}
/***** Get parameters from form *****/
/* Get the new name for the course */
2017-03-07 11:03:05 +01:00
Par_GetParToText (ParamName,NewCrsName,MaxBytes);
2014-12-01 23:55:08 +01:00
/***** Get from the database the data of the degree *****/
Crs_GetDataOfCourseByCod (Crs);
if (Crs_CheckIfICanEdit (Crs))
{
/***** Check if new name is empty *****/
if (!NewCrsName[0])
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_You_can_not_leave_the_name_of_the_course_X_empty,
CurrentCrsName);
2014-12-01 23:55:08 +01:00
else
{
2019-01-02 15:10:51 +01:00
/***** Check if old and new names are the same
(this happens when return is pressed without changes) *****/
2014-12-01 23:55:08 +01:00
if (strcmp (CurrentCrsName,NewCrsName)) // Different names
{
/***** If course was in database... *****/
2016-10-20 19:46:06 +02:00
if (Crs_CheckIfCrsNameExistsInYearOfDeg (ParamName,NewCrsName,Crs->CrsCod,
Crs->DegCod,Crs->Year))
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_The_course_X_already_exists,
NewCrsName);
2014-12-01 23:55:08 +01:00
else
{
/* Update the table changing old name by new name */
2017-03-09 11:16:17 +01:00
Crs_UpdateCrsNameDB (Crs->CrsCod,FieldName,NewCrsName);
2014-12-01 23:55:08 +01:00
2019-03-09 20:12:44 +01:00
/* Create alert to show the change made */
Ale_CreateAlert (Ale_SUCCESS,NULL,
Txt_The_name_of_the_course_X_has_changed_to_Y,
CurrentCrsName,NewCrsName);
2014-12-01 23:55:08 +01:00
2016-03-01 12:01:28 +01:00
/* Change current course name in order to display it properly */
2017-01-17 03:10:43 +01:00
Str_Copy (CurrentCrsName,NewCrsName,
2017-03-07 11:03:05 +01:00
MaxBytes);
2014-12-01 23:55:08 +01:00
}
}
else // The same name
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_INFO,NULL,
Txt_The_name_of_the_course_X_has_not_changed,
CurrentCrsName);
2014-12-01 23:55:08 +01:00
}
}
else
2019-02-16 20:44:31 +01:00
Lay_NoPermissionExit ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-03-09 11:16:17 +01:00
/********** Check if the name of course exists in existing courses ***********/
/*****************************************************************************/
static bool Crs_CheckIfCrsNameExistsInYearOfDeg (const char *FieldName,const char *Name,long CrsCod,
long DegCod,unsigned Year)
{
/***** Get number of courses in a year of a degree and with a name from database *****/
2018-11-03 13:13:11 +01:00
return (DB_QueryCOUNT ("can not check if the name"
" of a course already existed",
"SELECT COUNT(*) FROM courses"
" WHERE DegCod=%ld AND Year=%u"
" AND %s='%s' AND CrsCod<>%ld",
DegCod,Year,FieldName,Name,CrsCod) != 0);
2017-03-09 11:16:17 +01:00
}
/*****************************************************************************/
/***************** Update course name in table of courses ********************/
/*****************************************************************************/
static void Crs_UpdateCrsNameDB (long CrsCod,const char *FieldName,const char *NewCrsName)
{
/***** Update course changing old name by new name *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ("can not update the name of a course",
"UPDATE courses SET %s='%s' WHERE CrsCod=%ld",
FieldName,NewCrsName,CrsCod);
2017-03-09 11:16:17 +01:00
}
/*****************************************************************************/
2014-12-01 23:55:08 +01:00
/*********************** Change the status of a course ***********************/
/*****************************************************************************/
void Crs_ChangeCrsStatus (void)
{
extern const char *Txt_The_status_of_the_course_X_has_changed;
Crs_Status_t Status;
Crs_StatusTxt_t StatusTxt;
2019-04-07 19:49:53 +02:00
/***** Course constructor *****/
Crs_EditingCourseConstructor ();
2014-12-01 23:55:08 +01:00
/***** Get parameters from form *****/
/* Get course code */
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->CrsCod = Crs_GetAndCheckParamOtherCrsCod (1);
2014-12-01 23:55:08 +01:00
/* Get parameter with status */
2017-01-29 21:41:08 +01:00
Status = (Crs_Status_t)
Par_GetParToUnsignedLong ("Status",
0,
(unsigned long) Crs_MAX_STATUS,
(unsigned long) Crs_WRONG_STATUS);
2017-01-29 12:42:19 +01:00
if (Status == Crs_WRONG_STATUS)
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ("Wrong status.");
StatusTxt = Crs_GetStatusTxtFromStatusBits (Status);
Status = Crs_GetStatusBitsFromStatusTxt (StatusTxt); // New status
/***** Get data of course *****/
2019-04-07 19:49:53 +02:00
Crs_GetDataOfCourseByCod (Crs_EditingCrs);
2014-12-01 23:55:08 +01:00
/***** Update status in table of courses *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ("can not update the status of a course",
"UPDATE courses SET Status=%u WHERE CrsCod=%ld",
2019-04-07 19:49:53 +02:00
(unsigned) Status,Crs_EditingCrs->CrsCod);
Crs_EditingCrs->Status = Status;
2014-12-01 23:55:08 +01:00
2019-03-09 20:12:44 +01:00
/***** Create alert to show the change made *****/
Ale_CreateAlert (Ale_SUCCESS,NULL,
Txt_The_status_of_the_course_X_has_changed,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->ShrtName);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2019-04-08 14:52:13 +02:00
/********* Show alerts after changing a course and continue editing **********/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Crs_ContEditAfterChgCrs (void)
{
2016-03-24 20:13:42 +01:00
bool PutButtonToRequestRegistration;
2019-03-09 20:12:44 +01:00
if (Ale_GetTypeOfLastAlert () == Ale_SUCCESS)
2017-03-26 03:36:48 +02:00
{
2019-03-09 20:12:44 +01:00
/***** Start alert *****/
Ale_ShowLastAlertAndButton1 ();
2016-03-01 13:36:48 +01:00
/***** Put button to go to course changed *****/
2017-05-11 20:55:04 +02:00
Crs_PutButtonToGoToCrs ();
2016-03-24 20:13:42 +01:00
/***** Put button to request my registration in course *****/
PutButtonToRequestRegistration = false;
2017-06-04 18:18:54 +02:00
switch (Gbl.Usrs.Me.Role.Logged)
2016-03-24 20:13:42 +01:00
{
2017-05-18 19:13:41 +02:00
case Rol_GST: // I do not belong to any course
2016-03-24 20:13:42 +01:00
PutButtonToRequestRegistration = true;
break;
2017-05-18 19:13:41 +02:00
case Rol_USR:
2016-03-24 20:13:42 +01:00
PutButtonToRequestRegistration = !Usr_CheckIfUsrBelongsToCrs (Gbl.Usrs.Me.UsrDat.UsrCod,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->CrsCod,
2016-03-24 20:13:42 +01:00
false);
break;
2017-05-18 19:13:41 +02:00
case Rol_STD:
2017-05-21 21:23:13 +02:00
case Rol_NET:
2017-05-18 19:13:41 +02:00
case Rol_TCH:
2019-04-07 19:49:53 +02:00
if (Crs_EditingCrs->CrsCod != Gbl.Hierarchy.Crs.CrsCod)
2016-03-24 20:13:42 +01:00
PutButtonToRequestRegistration = !Usr_CheckIfUsrBelongsToCrs (Gbl.Usrs.Me.UsrDat.UsrCod,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->CrsCod,
2016-03-24 20:13:42 +01:00
false);
break;
default:
break;
}
if (PutButtonToRequestRegistration)
2017-05-11 20:55:04 +02:00
Crs_PutButtonToRegisterInCrs ();
2019-03-09 20:12:44 +01:00
/***** End alert *****/
Ale_ShowAlertAndButton2 (ActUnk,NULL,NULL,NULL,Btn_NO_BUTTON,NULL);
2016-03-01 13:36:48 +01:00
}
2014-12-01 23:55:08 +01:00
2019-03-09 20:12:44 +01:00
/***** Show possible delayed alerts *****/
Ale_ShowAlerts (NULL);
2017-05-11 20:04:38 +02:00
2014-12-01 23:55:08 +01:00
/***** Show the form again *****/
2019-04-07 19:49:53 +02:00
Crs_EditCoursesInternal ();
/***** Course destructor *****/
Crs_EditingCourseDestructor ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2016-03-01 12:01:28 +01:00
/************************ Put button to go to course *************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-05-11 20:55:04 +02:00
static void Crs_PutButtonToGoToCrs (void)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Go_to_X;
2017-05-11 20:55:04 +02:00
// If the course being edited is different to the current one...
2019-04-07 19:49:53 +02:00
if (Crs_EditingCrs->CrsCod != Gbl.Hierarchy.Crs.CrsCod)
2016-03-01 23:58:48 +01:00
{
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActSeeCrsInf);
2019-04-07 19:49:53 +02:00
Crs_PutParamCrsCod (Crs_EditingCrs->CrsCod);
2018-10-17 10:32:18 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Go_to_X,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->ShrtName);
2017-06-11 19:02:40 +02:00
Btn_PutConfirmButton (Gbl.Title);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-03-01 23:58:48 +01:00
}
2014-12-01 23:55:08 +01:00
}
2016-03-24 20:13:42 +01:00
/*****************************************************************************/
/************************ Put button to go to course *************************/
/*****************************************************************************/
2017-05-11 20:55:04 +02:00
static void Crs_PutButtonToRegisterInCrs (void)
2016-03-24 20:13:42 +01:00
{
extern const char *Txt_Register_me_in_X;
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActReqSignUp);
2019-04-08 23:34:58 +02:00
// If the course being edited is different to the current one...
2019-04-07 19:49:53 +02:00
if (Crs_EditingCrs->CrsCod != Gbl.Hierarchy.Crs.CrsCod)
Crs_PutParamCrsCod (Crs_EditingCrs->CrsCod);
2018-10-17 10:32:18 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Register_me_in_X,
2019-04-07 19:49:53 +02:00
Crs_EditingCrs->ShrtName);
2017-06-11 19:02:40 +02:00
Btn_PutCreateButton (Gbl.Title);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2016-03-24 20:13:42 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************************* Select one of my courses **************************/
/*****************************************************************************/
void Crs_ReqSelectOneOfMyCourses (void)
{
2018-10-09 13:08:41 +02:00
/***** Fill the list with the courses I belong to, if not filled *****/
2014-12-01 23:55:08 +01:00
Usr_GetMyCourses ();
2018-10-09 13:08:41 +02:00
/***** Select one of my courses *****/
2016-10-28 10:03:37 +02:00
if (Gbl.Usrs.Me.MyCrss.Num)
2015-10-06 01:19:21 +02:00
/* Show my courses */
2014-12-01 23:55:08 +01:00
Crs_WriteListMyCoursesToSelectOne ();
2017-03-30 11:20:06 +02:00
else // I am not enroled in any course
/* Show help to enrol me */
2015-10-06 20:34:49 +02:00
Hlp_ShowHelpWhatWouldYouLikeToDo ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2018-10-09 13:08:41 +02:00
/******************* Put an icon (form) to search courses ********************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2018-10-09 13:08:41 +02:00
static void Crs_PutIconToSearchCourses (void)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Search_courses;
/***** Put form to search / select courses *****/
2019-02-15 13:39:37 +01:00
Lay_PutContextualLinkOnlyIcon (ActReqSch,
2019-01-12 03:00:59 +01:00
NULL,Sch_PutLinkToSearchCoursesParams,
"search.svg",
Txt_Search_courses);
2015-04-02 18:39:49 +02:00
}
2016-06-24 20:34:58 +02:00
static void Sch_PutLinkToSearchCoursesParams (void) // TODO: Move to search module
2015-04-02 18:39:49 +02:00
{
2019-04-03 20:57:04 +02:00
Sco_PutParamScope ("ScopeSch",Hie_SYS);
2014-12-13 17:17:42 +01:00
Par_PutHiddenParamUnsigned ("WhatToSearch",(unsigned) Sch_SEARCH_COURSES);
2014-12-01 23:55:08 +01:00
}
2018-10-09 17:56:18 +02:00
/*****************************************************************************/
/********** Put an icon (form) to select my courses in breadcrumb ************/
/*****************************************************************************/
void Crs_PutIconToSelectMyCoursesInBreadcrumb (void)
{
extern const char *Txt_My_courses;
2018-10-10 08:59:26 +02:00
if (Gbl.Usrs.Me.Logged) // I am logged
{
2019-01-11 12:47:02 +01:00
/***** Start form *****/
Frm_StartForm (ActMyCrs);
2018-10-09 17:56:18 +02:00
2019-01-11 12:47:02 +01:00
/***** Put icon with link *****/
Frm_LinkFormSubmit (Txt_My_courses,NULL,NULL);
fprintf (Gbl.F.Out,"<img src=\"%s/sitemap.svg\""
" alt=\"%s\" title=\"%s\""
" class=\"BC_ICON ICO_HIGHLIGHT\" />"
"</a>",
Gbl.Prefs.URLTheme,
Txt_My_courses,Txt_My_courses);
/***** End form *****/
Frm_EndForm ();
2018-10-10 08:59:26 +02:00
}
2018-10-09 17:56:18 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2018-10-09 13:41:55 +02:00
/****************** Put an icon (form) to select my courses ******************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2018-10-09 13:41:55 +02:00
void Crs_PutIconToSelectMyCourses (void)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_My_courses;
2019-01-11 12:47:02 +01:00
if (Gbl.Usrs.Me.Logged) // I am logged
/***** Put icon with link *****/
2019-01-12 03:00:59 +01:00
Lay_PutContextualLinkOnlyIcon (ActMyCrs,NULL,NULL,
"sitemap.svg",
Txt_My_courses);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Write parameter with code of course ********************/
/*****************************************************************************/
void Crs_PutParamCrsCod (long CrsCod)
{
2015-03-07 21:08:44 +01:00
Par_PutHiddenParamLong ("crs",CrsCod);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Write parameter with code of course ********************/
/*****************************************************************************/
static void Crs_PutParamOtherCrsCod (long CrsCod)
{
Par_PutHiddenParamLong ("OthCrsCod",CrsCod);
}
/*****************************************************************************/
/********************* Get parameter with code of course *********************/
/*****************************************************************************/
2017-05-31 21:05:59 +02:00
static long Crs_GetAndCheckParamOtherCrsCod (long MinCodAllowed)
2014-12-01 23:55:08 +01:00
{
2016-10-23 18:32:46 +02:00
long CrsCod;
2014-12-01 23:55:08 +01:00
2016-10-23 19:40:14 +02:00
/***** Get and check parameter with code of course *****/
2017-05-31 21:05:59 +02:00
if ((CrsCod = Par_GetParToLong ("OthCrsCod")) < MinCodAllowed)
Lay_ShowErrorAndExit ("Code of course is missing or invalid.");
2016-10-23 18:32:46 +02:00
return CrsCod;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************** Write courses of a user **************************/
/*****************************************************************************/
2016-06-16 11:28:20 +02:00
void Crs_GetAndWriteCrssOfAUsr (const struct UsrData *UsrDat,Rol_Role_t Role)
2014-12-01 23:55:08 +01:00
{
2016-06-16 11:28:20 +02:00
extern const char *Txt_USER_in_COURSE;
2016-09-22 22:09:24 +02:00
extern const char *Txt_User[Usr_NUM_SEXS];
2016-06-16 11:28:20 +02:00
extern const char *Txt_ROLES_SINGUL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
2014-12-01 23:55:08 +01:00
extern const char *Txt_Degree;
extern const char *Txt_Year_OF_A_DEGREE;
extern const char *Txt_Course;
2017-05-30 21:43:05 +02:00
extern const char *Txt_ROLES_PLURAL_BRIEF_Abc[Rol_NUM_ROLES];
2018-10-30 01:00:46 +01:00
char *SubQuery;
2014-12-01 23:55:08 +01:00
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumCrss;
unsigned NumCrs;
/***** Get courses of a user from database *****/
2018-10-30 01:00:46 +01:00
if (Role == Rol_UNK) // Role == Rol_UNK ==> any role
{
if (asprintf (&SubQuery,"%s","") < 0)
Lay_NotEnoughMemoryExit ();
}
2016-09-08 21:40:31 +02:00
else
2018-10-30 01:00:46 +01:00
{
if (asprintf (&SubQuery," AND crs_usr.Role=%u",(unsigned) Role) < 0)
Lay_NotEnoughMemoryExit ();
}
2018-10-30 14:47:31 +01:00
NumCrss = (unsigned) DB_QuerySELECT (&mysql_res,"can not get courses of a user",
"SELECT degrees.DegCod,courses.CrsCod,degrees.ShortName,degrees.FullName,"
"courses.Year,courses.FullName,centres.ShortName,crs_usr.Accepted"
" FROM crs_usr,courses,degrees,centres"
" WHERE crs_usr.UsrCod=%ld%s"
" AND crs_usr.CrsCod=courses.CrsCod"
" AND courses.DegCod=degrees.DegCod"
" AND degrees.CtrCod=centres.CtrCod"
" ORDER BY degrees.FullName,courses.Year,courses.FullName",
UsrDat->UsrCod,SubQuery);
2018-10-30 01:00:46 +01:00
/***** Free allocated memory for subquery *****/
free ((void *) SubQuery);
2014-12-01 23:55:08 +01:00
/***** List the courses (one row per course) *****/
2018-10-30 01:00:46 +01:00
if (NumCrss)
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 ("100%",NULL,NULL,
2017-06-12 15:03:29 +02:00
NULL,Box_NOT_CLOSABLE,2);
2016-06-15 20:35:49 +02:00
2014-12-01 23:55:08 +01:00
/* Heading row */
2018-10-17 10:32:18 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_USER_in_COURSE,
Role == Rol_UNK ? Txt_User[Usr_SEX_UNKNOWN] : // Role == Rol_UNK ==> any role
Txt_ROLES_SINGUL_Abc[Role][UsrDat->Sex]);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<tr>"
2016-09-11 18:31:11 +02:00
"<th colspan=\"7\" class=\"LEFT_MIDDLE\">%s:</th>"
2016-06-16 11:28:20 +02:00
"</tr>"
"<tr>"
2014-12-01 23:55:08 +01:00
"<th class=\"BM\"></th>"
"<th class=\"BM\"></th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_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=\"LEFT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
2016-06-16 11:28:20 +02:00
Gbl.Title,
2014-12-01 23:55:08 +01:00
Txt_Degree,
Txt_Year_OF_A_DEGREE,
Txt_Course,
2017-05-30 21:43:05 +02:00
Txt_ROLES_PLURAL_BRIEF_Abc[Rol_TCH],
Txt_ROLES_PLURAL_BRIEF_Abc[Rol_STD]);
2014-12-01 23:55:08 +01:00
/* Write courses */
for (NumCrs = 1;
NumCrs <= NumCrss;
NumCrs++)
{
/* Get next course */
row = mysql_fetch_row (mysql_res);
/* Write data of this course */
Crs_WriteRowCrsData (NumCrs,row,true);
}
2016-06-15 20:35:49 +02:00
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 structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
2018-10-30 17:47:57 +01:00
/**************************** List courses found *****************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2018-10-30 14:47:31 +01:00
void Crs_ListCrssFound (MYSQL_RES **mysql_res,unsigned NumCrss)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_course;
extern const char *Txt_courses;
extern const char *Txt_Degree;
extern const char *Txt_Year_OF_A_DEGREE;
extern const char *Txt_Course;
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
MYSQL_ROW row;
unsigned NumCrs;
/***** List the courses (one row per course) *****/
if (NumCrss)
{
2017-06-12 14:16:33 +02:00
/***** Start box and table *****/
2014-12-01 23:55:08 +01:00
/* Number of courses found */
2018-10-17 10:32:18 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
"%u %s",
NumCrss,(NumCrss == 1) ? Txt_course :
Txt_courses);
2017-06-10 21:38:10 +02:00
Box_StartBoxTable (NULL,Gbl.Title,NULL,
2017-06-12 15:03:29 +02:00
NULL,Box_NOT_CLOSABLE,2);
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** Heading row *****/
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,"<tr>"
"<th class=\"BM\"></th>"
2015-09-06 20:02:14 +02:00
"<th class=\"LEFT_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=\"LEFT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2015-09-06 20:02:14 +02:00
"<th class=\"RIGHT_MIDDLE\">"
2014-12-26 22:11:03 +01:00
"%s"
"</th>"
2014-12-01 23:55:08 +01:00
"</tr>",
Txt_Degree,
Txt_Year_OF_A_DEGREE,
Txt_Course,
2017-07-02 19:51:55 +02:00
Txt_ROLES_PLURAL_BRIEF_Abc[Rol_TCH],
Txt_ROLES_PLURAL_BRIEF_Abc[Rol_STD]);
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** Write courses *****/
2014-12-01 23:55:08 +01:00
for (NumCrs = 1;
NumCrs <= NumCrss;
NumCrs++)
{
/* Get next course */
2018-10-30 14:47:31 +01:00
row = mysql_fetch_row (*mysql_res);
2014-12-01 23:55:08 +01:00
/* Write data of this course */
Crs_WriteRowCrsData (NumCrs,row,false);
}
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 structure that stores the query result *****/
2018-10-30 14:47:31 +01:00
DB_FreeMySQLResult (mysql_res);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************** Write the data of a course (result of a query) ***************/
/*****************************************************************************/
static void Crs_WriteRowCrsData (unsigned NumCrs,MYSQL_ROW row,bool WriteColumnAccepted)
{
2017-03-30 11:20:06 +02:00
extern const char *Txt_Enrolment_confirmed;
extern const char *Txt_Enrolment_not_confirmed;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Go_to_X;
2017-01-28 15:58:46 +01:00
extern const char *Txt_YEAR_OF_DEGREE[1 + Deg_MAX_YEARS_PER_DEGREE];
2015-01-17 19:31:21 +01:00
struct Degree Deg;
2014-12-01 23:55:08 +01:00
long CrsCod;
unsigned NumTchs;
2016-06-04 13:07:33 +02:00
unsigned NumStds;
2014-12-01 23:55:08 +01:00
const char *Style;
const char *StyleNoBR;
2015-09-04 19:26:08 +02:00
const char *BgColor;
2014-12-01 23:55:08 +01:00
bool Accepted;
2016-06-16 11:28:20 +02:00
static unsigned RowEvenOdd = 1;
2014-12-01 23:55:08 +01:00
2015-01-21 10:26:08 +01:00
/*
2016-06-12 13:47:19 +02:00
SELECT degrees.DegCod 0
courses.CrsCod 1
degrees.ShortName 2
degrees.FullName 3
courses.Year 4
courses.FullName 5
centres.ShortName 6
crs_usr.Accepted 7 (only if WriteColumnAccepted == true)
2015-01-21 10:26:08 +01:00
*/
2014-12-01 23:55:08 +01:00
/***** Get degree code (row[0]) *****/
2015-01-17 19:31:21 +01:00
if ((Deg.DegCod = Str_ConvertStrCodToLongCod (row[0])) < 0)
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ("Wrong code of degree.");
2015-01-17 19:31:21 +01:00
if (!Deg_GetDataOfDegreeByCod (&Deg))
Lay_ShowErrorAndExit ("Degree not found.");
2014-12-01 23:55:08 +01:00
/***** Get course code (row[1]) *****/
if ((CrsCod = Str_ConvertStrCodToLongCod (row[1])) < 0)
Lay_ShowErrorAndExit ("Wrong code of course.");
2016-06-04 13:07:33 +02:00
/***** Get number of teachers and students in this course *****/
2017-05-29 13:20:48 +02:00
NumTchs = Usr_GetNumUsrsInCrs (Rol_TCH,CrsCod) +
2017-05-21 21:23:13 +02:00
Usr_GetNumUsrsInCrs (Rol_NET,CrsCod);
2017-05-29 13:20:48 +02:00
NumStds = Usr_GetNumUsrsInCrs (Rol_STD,CrsCod);
2016-06-04 13:07:33 +02:00
if (NumTchs + NumStds)
2014-12-01 23:55:08 +01:00
{
Style = "DAT_N";
2016-01-01 21:18:44 +01:00
StyleNoBR = "DAT_NOBR_N";
2014-12-01 23:55:08 +01:00
}
else
{
Style = "DAT";
StyleNoBR = "DAT_NOBR";
}
2019-04-04 10:45:15 +02:00
BgColor = (CrsCod == Gbl.Hierarchy.Crs.CrsCod) ? "LIGHT_BLUE" :
2016-06-16 11:28:20 +02:00
Gbl.ColorRows[RowEvenOdd];
2014-12-01 23:55:08 +01:00
/***** Start row *****/
fprintf (Gbl.F.Out,"<tr>");
2016-06-16 11:28:20 +02:00
/***** User has accepted joining to this course/to any course in degree/to any course? *****/
2014-12-01 23:55:08 +01:00
if (WriteColumnAccepted)
{
2016-09-07 18:48:10 +02:00
Accepted = (row[7][0] == 'Y');
2018-12-08 19:30:14 +01:00
fprintf (Gbl.F.Out,"<td class=\"BT %s\" title=\"%s\">"
"%s"
2014-12-01 23:55:08 +01:00
"</td>",
BgColor,
2017-03-30 11:20:06 +02:00
Accepted ? Txt_Enrolment_confirmed :
Txt_Enrolment_not_confirmed,
2018-12-08 19:30:14 +01:00
Accepted ? "&check;" :
"&cross;");
2014-12-01 23:55:08 +01:00
}
/***** Write number of course in this search *****/
2015-09-04 17:10:27 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s RIGHT_TOP %s\">"
2014-12-22 19:59:27 +01:00
"%u"
"</td>",
2014-12-01 23:55:08 +01:00
StyleNoBR,BgColor,NumCrs);
2015-09-04 17:10:27 +02:00
/***** Write degree logo, degree short name (row[2])
2015-12-06 01:02:47 +01:00
and centre short name (row[6]) *****/
2015-09-04 17:10:27 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s LEFT_TOP %s\">",
2014-12-01 23:55:08 +01:00
StyleNoBR,BgColor);
2018-11-09 20:47:39 +01:00
Frm_StartFormGoTo (ActSeeDegInf);
2015-01-17 19:31:21 +01:00
Deg_PutParamDegCod (Deg.DegCod);
2018-10-17 10:32:18 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Go_to_X,
row[2]);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Gbl.Title,StyleNoBR,NULL);
2019-04-03 20:57:04 +02:00
Log_DrawLogo (Hie_DEG,Deg.DegCod,Deg.ShrtName,20,"CENTER_TOP",true);
2015-01-17 19:31:21 +01:00
fprintf (Gbl.F.Out," %s (%s)"
2015-03-13 00:16:02 +01:00
"</a>",
2015-12-06 01:02:47 +01:00
row[2],row[6]);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2015-03-13 00:16:02 +01:00
fprintf (Gbl.F.Out,"</td>");
2014-12-01 23:55:08 +01:00
2015-01-17 19:31:21 +01:00
/***** Write year (row[4]) *****/
2015-09-04 17:10:27 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s CENTER_TOP %s\">"
2014-12-22 19:59:27 +01:00
"%s"
"</td>",
2015-01-17 19:31:21 +01:00
Style,BgColor,Txt_YEAR_OF_DEGREE[Deg_ConvStrToYear (row[4])]);
2014-12-01 23:55:08 +01:00
2015-12-06 01:02:47 +01:00
/***** Write course full name (row[5]) *****/
2015-09-04 17:10:27 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s LEFT_TOP %s\">",
2014-12-01 23:55:08 +01:00
Style,BgColor);
2018-11-09 20:47:39 +01:00
Frm_StartFormGoTo (ActSeeCrsInf);
2014-12-01 23:55:08 +01:00
Crs_PutParamCrsCod (CrsCod);
2018-10-17 10:32:18 +02:00
snprintf (Gbl.Title,sizeof (Gbl.Title),
Txt_Go_to_X,
row[6]);
2018-11-09 20:47:39 +01:00
Frm_LinkFormSubmit (Gbl.Title,Style,NULL);
2015-12-06 01:02:47 +01:00
fprintf (Gbl.F.Out,"%s</a>",row[5]);
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2015-03-13 00:16:02 +01:00
fprintf (Gbl.F.Out,"</td>");
2014-12-01 23:55:08 +01:00
/***** Write number of teachers in course *****/
2015-09-04 17:10:27 +02:00
fprintf (Gbl.F.Out,"<td class=\"%s RIGHT_TOP %s\">"
2014-12-22 19:59:27 +01:00
"%u"
2016-06-11 21:02:36 +02:00
"</td>",
2014-12-01 23:55:08 +01:00
Style,BgColor,NumTchs);
2016-06-04 13:07:33 +02:00
/***** Write number of students in course *****/
fprintf (Gbl.F.Out,"<td class=\"%s RIGHT_TOP %s\">"
"%u"
2016-06-11 21:02:36 +02:00
"</td>"
"</tr>",
2016-06-04 13:07:33 +02:00
Style,BgColor,NumStds);
2016-06-16 11:28:20 +02:00
RowEvenOdd = 1 - RowEvenOdd;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************** Update my last click in current course ********************/
/*****************************************************************************/
void Crs_UpdateCrsLast (void)
{
2019-04-03 20:57:04 +02:00
if (Gbl.Hierarchy.Level == Hie_CRS && // Course selected
2017-06-04 18:18:54 +02:00
Gbl.Usrs.Me.Role.Logged >= Rol_STD)
2014-12-01 23:55:08 +01:00
/***** Update my last access to current course *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ("can not update last access to current course",
"REPLACE INTO crs_last (CrsCod,LastTime)"
" VALUES (%ld,NOW())",
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod);
2014-12-01 23:55:08 +01:00
}
2017-03-27 01:14:38 +02:00
/*****************************************************************************/
/********************** Put link to remove old courses ***********************/
/*****************************************************************************/
void Crs_PutLinkToRemoveOldCrss (void)
{
extern const char *Txt_Eliminate_old_courses;
/***** Put form to remove old courses *****/
2019-01-12 03:00:59 +01:00
Lay_PutContextualLinkIconText (ActReqRemOldCrs,NULL,NULL,
"trash.svg",
Txt_Eliminate_old_courses);
2017-03-27 01:14:38 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/********************** Write form to remove old courses *********************/
/*****************************************************************************/
void Crs_AskRemoveOldCrss (void)
{
2017-03-27 13:38:10 +02:00
extern const char *Hlp_SYSTEM_Hierarchy_eliminate_old_courses;
2019-02-22 21:47:50 +01:00
extern const char *The_ClassFormInBox[The_NUM_THEMES];
2015-10-07 23:03:30 +02:00
extern const char *Txt_Eliminate_old_courses;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Eliminate_all_courses_whithout_users_PART_1_OF_2;
extern const char *Txt_Eliminate_all_courses_whithout_users_PART_2_OF_2;
extern const char *Txt_Eliminate;
unsigned MonthsWithoutAccess = Crs_DEF_MONTHS_WITHOUT_ACCESS_TO_REMOVE_OLD_CRSS;
unsigned i;
2015-10-07 23:03:30 +02:00
/***** Start form *****/
2018-11-09 20:47:39 +01:00
Frm_StartForm (ActRemOldCrs);
2015-10-07 23:03:30 +02:00
2017-06-12 14:16:33 +02:00
/***** Start box *****/
2017-06-10 21:38:10 +02:00
Box_StartBox (NULL,Txt_Eliminate_old_courses,NULL,
2017-06-12 15:03:29 +02:00
Hlp_SYSTEM_Hierarchy_eliminate_old_courses,Box_NOT_CLOSABLE);
2015-10-07 23:03:30 +02:00
/***** Form to request number of months without clicks *****/
2016-12-27 16:45:37 +01:00
fprintf (Gbl.F.Out,"<label class=\"%s\">%s&nbsp;"
"<select name=\"Months\">",
2019-02-22 21:47:50 +01:00
The_ClassFormInBox[Gbl.Prefs.Theme],
2014-12-01 23:55:08 +01:00
Txt_Eliminate_all_courses_whithout_users_PART_1_OF_2);
for (i = Crs_MIN_MONTHS_WITHOUT_ACCESS_TO_REMOVE_OLD_CRSS;
i <= Crs_MAX_MONTHS_WITHOUT_ACCESS_TO_REMOVE_OLD_CRSS;
i++)
{
fprintf (Gbl.F.Out,"<option");
if (i == MonthsWithoutAccess)
fprintf (Gbl.F.Out," selected=\"selected\"");
fprintf (Gbl.F.Out,">%u</option>",i);
}
2016-12-27 16:45:37 +01:00
fprintf (Gbl.F.Out,"</select>&nbsp;");
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.Out,Txt_Eliminate_all_courses_whithout_users_PART_2_OF_2,
Cfg_PLATFORM_SHORT_NAME);
2016-12-27 16:45:37 +01:00
fprintf (Gbl.F.Out,"</label>");
2014-12-01 23:55:08 +01:00
2017-06-12 14:16:33 +02:00
/***** Send button and end box *****/
2017-06-11 19:02:40 +02:00
Box_EndBoxWithButton (Btn_REMOVE_BUTTON,Txt_Eliminate);
2015-10-07 23:03:30 +02:00
/***** End form *****/
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/**************************** Remove old courses *****************************/
/*****************************************************************************/
void Crs_RemoveOldCrss (void)
{
extern const char *Txt_Eliminating_X_courses_whithout_users_and_with_more_than_Y_months_without_access;
extern const char *Txt_X_courses_have_been_eliminated;
unsigned MonthsWithoutAccess;
unsigned long SecondsWithoutAccess;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumCrs;
unsigned long NumCrss;
unsigned NumCrssRemoved = 0;
long CrsCod;
/***** Get parameter with number of months without access *****/
2017-01-29 21:41:08 +01:00
MonthsWithoutAccess = (unsigned)
Par_GetParToUnsignedLong ("Months",
Crs_MIN_MONTHS_WITHOUT_ACCESS_TO_REMOVE_OLD_CRSS,
Crs_MAX_MONTHS_WITHOUT_ACCESS_TO_REMOVE_OLD_CRSS,
UINT_MAX);
2017-01-29 12:42:19 +01:00
if (MonthsWithoutAccess == UINT_MAX)
2014-12-01 23:55:08 +01:00
Lay_ShowErrorAndExit ("Wrong number of months without clicks.");
SecondsWithoutAccess = (unsigned long) MonthsWithoutAccess * Dat_SECONDS_IN_ONE_MONTH;
/***** Get old courses from database *****/
2018-10-30 14:47:31 +01:00
NumCrss = DB_QuerySELECT (&mysql_res,"can not get old courses",
"SELECT CrsCod FROM crs_last WHERE"
2019-02-13 13:32:11 +01:00
" LastTime<FROM_UNIXTIME(UNIX_TIMESTAMP()-%lu)"
2018-10-30 14:47:31 +01:00
" AND CrsCod NOT IN (SELECT DISTINCT CrsCod FROM crs_usr)",
SecondsWithoutAccess);
if (NumCrss)
2014-12-01 23:55:08 +01:00
{
2019-02-16 14:37:34 +01:00
Ale_ShowAlert (Ale_INFO,Txt_Eliminating_X_courses_whithout_users_and_with_more_than_Y_months_without_access,
2019-02-16 00:15:59 +01:00
NumCrss,
MonthsWithoutAccess,
Cfg_PLATFORM_SHORT_NAME);
2014-12-01 23:55:08 +01:00
/***** Remove courses *****/
for (NumCrs = 0;
NumCrs < NumCrss;
NumCrs++)
{
row = mysql_fetch_row (mysql_res);
CrsCod = Str_ConvertStrCodToLongCod (row[0]);
Crs_RemoveCourseCompletely (CrsCod);
NumCrssRemoved++;
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/***** Write end message *****/
2019-02-16 14:37:34 +01:00
Ale_ShowAlert (Ale_SUCCESS,Txt_X_courses_have_been_eliminated,
2019-02-16 00:15:59 +01:00
NumCrssRemoved);
2014-12-01 23:55:08 +01:00
}
2019-04-07 19:49:53 +02:00
/*****************************************************************************/
/************************ Course constructor/destructor **********************/
/*****************************************************************************/
static void Crs_EditingCourseConstructor (void)
{
Rol_Role_t Role;
/***** Pointer must be NULL *****/
if (Crs_EditingCrs != NULL)
Lay_ShowErrorAndExit ("Error initializing course.");
/***** Allocate memory for course *****/
if ((Crs_EditingCrs = (struct Course *) malloc (sizeof (struct Course))) == NULL)
Lay_ShowErrorAndExit ("Error allocating memory for course.");
/***** Reset course *****/
Crs_EditingCrs->CrsCod = -1L;
Crs_EditingCrs->InstitutionalCrsCod[0] = '\0';
Crs_EditingCrs->DegCod = -1L;
Crs_EditingCrs->Year = 0;
Crs_EditingCrs->Status = 0;
Crs_EditingCrs->ShrtName[0] = '\0';
Crs_EditingCrs->FullName[0] = '\0';
for (Role = (Rol_Role_t) 0;
Role < Rol_NUM_ROLES;
Role++)
Crs_EditingCrs->NumUsrs[Role] = 0;
}
static void Crs_EditingCourseDestructor (void)
{
/***** Free memory used for course *****/
if (Crs_EditingCrs != NULL)
{
free ((void *) Crs_EditingCrs);
Crs_EditingCrs = NULL;
}
}