swad-core/swad_agenda.c

1740 lines
61 KiB
C

// swad_agenda.c: user's agenda (personal organizer)
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2017 Antonio Cañas Vargas
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General 3 License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
#include <linux/limits.h> // For PATH_MAX
#include <linux/stddef.h> // For NULL
#include <stdlib.h> // For calloc
#include <string.h> // For string functions
#include "swad_agenda.h"
#include "swad_database.h"
#include "swad_global.h"
#include "swad_group.h"
#include "swad_notification.h"
#include "swad_pagination.h"
#include "swad_parameter.h"
#include "swad_photo.h"
#include "swad_privacy.h"
#include "swad_QR.h"
#include "swad_string.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
/*****************************************************************************/
/******************************* Private types *******************************/
/*****************************************************************************/
#define Agd_NUM_AGENDA_TYPES 6
typedef enum
{
Agd_MY_FULL_AGENDA_TODAY,
Agd_MY_FULL_AGENDA,
Agd_MY_PUBLIC_AGENDA_TODAY,
Agd_MY_PUBLIC_AGENDA,
Agd_OTHER_PUBLIC_AGENDA_TODAY,
Agd_OTHER_PUBLIC_AGENDA,
} Agd_AgendaType_t;
/*****************************************************************************/
/***************************** Private variables *****************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static void Agd_ShowEvents (Agd_AgendaType_t AgendaType);
static void Agd_ShowEventsToday (Agd_AgendaType_t AgendaType);
static void Agd_WriteHeaderListEvents (Agd_AgendaType_t AgendaType);
static void Agd_PutIconsMyFullAgenda (void);
static void Agd_PutIconsMyPublicAgenda (void);
static void Agd_PutIconToViewMyPublicAgenda (void);
static void Agd_PutIconToCreateNewEvent (void);
static void Agd_PutIconToViewEditMyFullAgenda (void);
static void Agd_PutIconToShowQR (void);
static void Agd_PutIconsOtherPublicAgenda (void);
static void Agd_PutButtonToCreateNewEvent (void);
static void Agd_PutParamsToCreateNewEvent (void);
static void Agd_ShowOneEvent (Agd_AgendaType_t AgendaType,long AgdCod);
static void Agd_GetParamEventOrder (void);
static void Agd_PutFormsToRemEditOneEvent (struct AgendaEvent *AgdEvent);
static void Agd_PutParams (void);
static void Agd_GetListEvents (Agd_AgendaType_t AgendaType);
static void Agd_GetDataOfEventByCod (struct AgendaEvent *AgdEvent);
static void Agd_GetEventTxtFromDB (struct AgendaEvent *AgdEvent,
char Txt[Cns_MAX_BYTES_TEXT + 1]);
static void Agd_PutParamAgdCod (long AgdCod);
static bool Agd_CheckIfSimilarEventExists (struct AgendaEvent *AgdEvent);
static void Agd_CreateEvent (struct AgendaEvent *AgdEvent,const char *Txt);
static void Agd_UpdateEvent (struct AgendaEvent *AgdEvent,const char *Txt);
/*****************************************************************************/
/********** Put form to log in and then show another user's agenda ***********/
/*****************************************************************************/
void Agd_PutFormLogInToShowUsrAgenda (void)
{
/***** Form to log in *****/
Usr_WriteFormLogin (ActLogInUsrAgd,Agd_PutParamAgd);
}
void Agd_PutParamAgd (void)
{
char Nickname[Nck_MAX_BYTES_NICKNAME_FROM_FORM + 1];
sprintf (Nickname,"@%s",Gbl.Usrs.Other.UsrDat.Nickname);
Par_PutHiddenParamString ("agd",Nickname);
}
/*****************************************************************************/
/******************************* Show my agenda ******************************/
/*****************************************************************************/
void Agd_ShowMyAgenda (void)
{
extern const char *Hlp_PROFILE_Agenda;
extern const char *Txt_My_agenda;
/***** Start frame *****/
Lay_StartRoundFrame ("100%",Txt_My_agenda,
Agd_PutIconsMyFullAgenda,Hlp_PROFILE_Agenda);
/***** Show the current events in the user's agenda *****/
Agd_ShowEventsToday (Agd_MY_FULL_AGENDA_TODAY);
/***** Show all my events *****/
Agd_ShowEvents (Agd_MY_FULL_AGENDA);
/***** End frame *****/
Lay_EndRoundFrame ();
}
/*****************************************************************************/
/*************************** Show my public agenda ***************************/
/*****************************************************************************/
void Agd_ShowMyPublicAgenda (void)
{
extern const char *Hlp_PROFILE_Agenda;
extern const char *Txt_Public_agenda_USER;
/***** Start frame *****/
sprintf (Gbl.Title,Txt_Public_agenda_USER,Gbl.Usrs.Me.UsrDat.FullName);
Lay_StartRoundFrame ("100%",Gbl.Title,
Agd_PutIconsMyPublicAgenda,Hlp_PROFILE_Agenda);
/***** Show the current events in the user's agenda *****/
Agd_ShowEventsToday (Agd_MY_PUBLIC_AGENDA_TODAY);
/***** Show all my events *****/
Agd_ShowEvents (Agd_MY_PUBLIC_AGENDA);
/***** End frame *****/
Lay_EndRoundFrame ();
}
/*****************************************************************************/
/************************ Show another user's agenda *************************/
/*****************************************************************************/
void Agd_ShowUsrAgenda (void)
{
extern const char *Hlp_PROFILE_Agenda_public_agenda;
extern const char *Txt_Public_agenda_USER;
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
bool ItsMe;
bool Error = true;
/***** Get user *****/
if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ())
if (Usr_CheckIfICanViewUsrAgenda (&Gbl.Usrs.Other.UsrDat))
{
Error = false;
/***** Start frame *****/
sprintf (Gbl.Title,Txt_Public_agenda_USER,Gbl.Usrs.Other.UsrDat.FullName);
ItsMe = (Gbl.Usrs.Me.UsrDat.UsrCod == Gbl.Usrs.Other.UsrDat.UsrCod);
Lay_StartRoundFrame ("100%",Gbl.Title,
ItsMe ? Agd_PutIconsMyPublicAgenda :
Agd_PutIconsOtherPublicAgenda,
Hlp_PROFILE_Agenda_public_agenda);
/***** Show the current events in the user's agenda *****/
Agd_ShowEventsToday (Agd_OTHER_PUBLIC_AGENDA_TODAY);
/***** Show all the visible events in the user's agenda *****/
Agd_ShowEvents (Agd_OTHER_PUBLIC_AGENDA);
/***** End frame *****/
Lay_EndRoundFrame ();
}
if (Error)
Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
}
/*****************************************************************************/
/***************** Show another user's agenda after log in *******************/
/*****************************************************************************/
void Agd_ShowOtherAgendaAfterLogIn (void)
{
extern const char *Hlp_PROFILE_Agenda_public_agenda;
extern const unsigned Txt_Current_CGI_SWAD_Language;
extern const char *Txt_Public_agenda_USER;
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
extern const char *Txt_Switching_to_LANGUAGE[1 + Txt_NUM_LANGUAGES];
bool ItsMe;
if (Gbl.Usrs.Me.Logged)
{
if (Gbl.Usrs.Me.UsrDat.Prefs.Language == Txt_Current_CGI_SWAD_Language)
{
/***** Get user *****/
/* If nickname is correct, user code is already got from nickname */
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat)) // Existing user
{
/***** Start frame *****/
sprintf (Gbl.Title,Txt_Public_agenda_USER,Gbl.Usrs.Other.UsrDat.FullName);
ItsMe = (Gbl.Usrs.Me.UsrDat.UsrCod == Gbl.Usrs.Other.UsrDat.UsrCod);
Lay_StartRoundFrame ("100%",Gbl.Title,
ItsMe ? Agd_PutIconToViewEditMyFullAgenda :
Agd_PutIconsOtherPublicAgenda,
Hlp_PROFILE_Agenda_public_agenda);
/***** Show the current events in the user's agenda *****/
Agd_ShowEventsToday (Agd_OTHER_PUBLIC_AGENDA_TODAY);
/***** Show all the visible events in the user's agenda *****/
Agd_ShowEvents (Agd_OTHER_PUBLIC_AGENDA);
/***** End frame *****/
Lay_EndRoundFrame ();
}
else
Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
}
else
/* The current language is not my preferred language
==> change automatically to my language */
Lay_ShowAlert (Lay_INFO,Txt_Switching_to_LANGUAGE[Gbl.Usrs.Me.UsrDat.Prefs.Language]);
}
}
/*****************************************************************************/
/*************************** Show events in agenda ***************************/
/*****************************************************************************/
static void Agd_ShowEvents (Agd_AgendaType_t AgendaType)
{
extern const char *Hlp_PROFILE_Agenda;
extern const char *Txt_Public_agenda_USER;
extern const char *Txt_My_agenda;
extern const char *Txt_No_events;
struct Pagination Pagination;
unsigned NumEvent;
Pag_WhatPaginate_t WhatPaginate[Agd_NUM_AGENDA_TYPES] =
{
Pag_MY_FULL_AGENDA, // Agd_MY_FULL_AGENDA_TODAY, not used
Pag_MY_FULL_AGENDA, // Agd_MY_FULL_AGENDA
Pag_MY_PUBLIC_AGENDA, // Agd_MY_PUBLIC_AGENDA_TODAY, not used
Pag_MY_PUBLIC_AGENDA, // Agd_MY_PUBLIC_AGENDA
Pag_OTHER_PUBLIC_AGENDA, // Agd_OTHER_PUBLIC_AGENDA_TODAY, not used
Pag_OTHER_PUBLIC_AGENDA, // Agd_OTHER_PUBLIC_AGENDA
};
/***** Get parameters *****/
Agd_GetParamEventOrder ();
Pag_GetParamPagNum (WhatPaginate[AgendaType]);
/***** Get list of events *****/
Agd_GetListEvents (AgendaType);
/***** Compute variables related to pagination *****/
Pagination.NumItems = Gbl.Agenda.Num;
Pagination.CurrentPage = (int) Gbl.Pag.CurrentPage;
Pag_CalculatePagination (&Pagination);
Gbl.Pag.CurrentPage = (unsigned) Pagination.CurrentPage;
/***** Write links to pages *****/
if (Pagination.MoreThanOnePage)
Pag_WriteLinksToPagesCentered (WhatPaginate[AgendaType],0,&Pagination);
if (Gbl.Agenda.Num)
{
/***** Start table *****/
fprintf (Gbl.F.Out,"<table class=\"FRAME_TBL_MARGIN CELLS_PAD_2\">");
/***** Table head *****/
Agd_WriteHeaderListEvents (AgendaType);
/***** Write all the events *****/
for (NumEvent = Pagination.FirstItemVisible;
NumEvent <= Pagination.LastItemVisible;
NumEvent++)
Agd_ShowOneEvent (AgendaType,Gbl.Agenda.LstAgdCods[NumEvent - 1]);
/***** End table *****/
fprintf (Gbl.F.Out,"</table>");
}
else
Lay_ShowAlert (Lay_INFO,Txt_No_events);
/***** Write again links to pages *****/
if (Pagination.MoreThanOnePage)
Pag_WriteLinksToPagesCentered (WhatPaginate[AgendaType],0,&Pagination);
/***** Button to create a new event *****/
if (AgendaType == Agd_MY_FULL_AGENDA)
Agd_PutButtonToCreateNewEvent ();
/***** Free list of events *****/
Agd_FreeListEvents ();
}
/*****************************************************************************/
/************************ Show today events in agenda ************************/
/*****************************************************************************/
static void Agd_ShowEventsToday (Agd_AgendaType_t AgendaType)
{
extern const char *Hlp_PROFILE_Agenda;
extern const char *Hlp_PROFILE_Agenda_public_agenda;
extern const char *Txt_Today;
extern const char *Txt_Public_agenda_USER;
extern const char *Txt_My_agenda;
extern const char *Txt_No_events;
unsigned NumEvent;
/***** Get parameters *****/
Agd_GetParamEventOrder ();
/***** Get list of events *****/
Agd_GetListEvents (AgendaType);
if (Gbl.Agenda.Num)
{
/***** Start frame *****/
switch (AgendaType)
{
case Agd_MY_FULL_AGENDA_TODAY:
case Agd_MY_PUBLIC_AGENDA_TODAY:
Lay_StartRoundFrameTableShadow (NULL,Txt_Today,
NULL,
Hlp_PROFILE_Agenda,
2);
break;
case Agd_OTHER_PUBLIC_AGENDA_TODAY:
Lay_StartRoundFrameTableShadow (NULL,Txt_Today,
NULL,
Hlp_PROFILE_Agenda_public_agenda,
2);
break;
default:
break;
}
/***** Table head *****/
Agd_WriteHeaderListEvents (AgendaType);
/***** Write all the events *****/
for (NumEvent = 0;
NumEvent < Gbl.Agenda.Num;
NumEvent++)
Agd_ShowOneEvent (AgendaType,Gbl.Agenda.LstAgdCods[NumEvent]);
/***** End table and frame *****/
Lay_EndRoundFrameTable ();
}
/***** Free list of events *****/
Agd_FreeListEvents ();
}
/*****************************************************************************/
/*************** Put contextual icon to view/edit my agenda ******************/
/*****************************************************************************/
static void Agd_WriteHeaderListEvents (Agd_AgendaType_t AgendaType)
{
extern const char *Txt_START_END_TIME_HELP[2];
extern const char *Txt_START_END_TIME[Dat_NUM_START_END_TIME];
extern const char *Txt_Event;
extern const char *Txt_Location;
Agd_Order_t Order;
/***** Table head *****/
fprintf (Gbl.F.Out,"<tr>");
for (Order = Agd_ORDER_BY_START_DATE;
Order <= Agd_ORDER_BY_END_DATE;
Order++)
{
fprintf (Gbl.F.Out,"<th class=\"LEFT_MIDDLE\">");
switch (AgendaType)
{
case Agd_MY_FULL_AGENDA_TODAY:
case Agd_MY_FULL_AGENDA:
Act_FormStart (ActSeeMyAgd);
break;
case Agd_MY_PUBLIC_AGENDA_TODAY:
case Agd_MY_PUBLIC_AGENDA:
Act_FormStart (ActSeeMyPubAgd);
break;
case Agd_OTHER_PUBLIC_AGENDA_TODAY:
case Agd_OTHER_PUBLIC_AGENDA:
Act_FormStart (ActSeeUsrAgd);
Usr_PutParamOtherUsrCodEncrypted ();
break;
}
Pag_PutHiddenParamPagNum (Gbl.Pag.CurrentPage);
Par_PutHiddenParamUnsigned ("Order",(unsigned) Order);
Act_LinkFormSubmit (Txt_START_END_TIME_HELP[Order],"TIT_TBL",NULL);
if (Order == Gbl.Agenda.SelectedOrder)
fprintf (Gbl.F.Out,"<u>");
fprintf (Gbl.F.Out,"%s",Txt_START_END_TIME[Order]);
if (Order == Gbl.Agenda.SelectedOrder)
fprintf (Gbl.F.Out,"</u>");
fprintf (Gbl.F.Out,"</a>");
Act_FormEnd ();
fprintf (Gbl.F.Out,"</th>");
}
fprintf (Gbl.F.Out,"<th class=\"LEFT_MIDDLE\">"
"%s"
"</th>"
"<th class=\"LEFT_MIDDLE\">"
"%s"
"</th>"
"</tr>",
Txt_Event,
Txt_Location);
}
/*****************************************************************************/
/********************** Put contextual icons in agenda ***********************/
/*****************************************************************************/
static void Agd_PutIconsMyFullAgenda (void)
{
/***** Put icon to create a new event *****/
Agd_PutIconToViewMyPublicAgenda ();
/***** Put icon to create a new event *****/
Agd_PutIconToCreateNewEvent ();
/***** Put icon to show QR code *****/
Agd_PutIconToShowQR ();
}
static void Agd_PutIconsMyPublicAgenda (void)
{
/***** Put icon to view/edit my full agenda *****/
Agd_PutIconToViewEditMyFullAgenda ();
/***** Put icon to show QR code *****/
Agd_PutIconToShowQR ();
}
static void Agd_PutIconToViewMyPublicAgenda (void)
{
extern const char *Txt_Public_agenda_USER;
/***** Put form to view my public agenda *****/
sprintf (Gbl.Title,Txt_Public_agenda_USER,Gbl.Usrs.Me.UsrDat.FullName);
Lay_PutContextualLink (ActSeeMyPubAgd,NULL,
"eye-on64x64.png",
Gbl.Title,NULL,
NULL);
}
static void Agd_PutIconToCreateNewEvent (void)
{
extern const char *Txt_New_event;
/***** Put form to create a new event *****/
Lay_PutContextualLink (ActFrmNewEvtMyAgd,Agd_PutParamsToCreateNewEvent,
"plus64x64.png",
Txt_New_event,NULL,
NULL);
}
static void Agd_PutIconToViewEditMyFullAgenda (void)
{
extern const char *Txt_Edit;
/***** Put form to create a new event *****/
Lay_PutContextualLink (ActSeeMyAgd,NULL,
"edit64x64.png",
Txt_Edit,NULL,
NULL);
}
static void Agd_PutIconToShowQR (void)
{
char URL[Cns_MAX_LENGTH_WWW + 1];
extern const char *Txt_STR_LANG_ID[1 + Txt_NUM_LANGUAGES];
sprintf (URL,"%s/%s?agd=@%s",
Cfg_URL_SWAD_CGI,
Txt_STR_LANG_ID[Gbl.Prefs.Language],
Gbl.Usrs.Me.UsrDat.Nickname);
Gbl.QR.Str = URL;
QR_PutLinkToPrintQRCode (ActPrnAgdQR,false);
}
static void Agd_PutIconsOtherPublicAgenda (void)
{
extern const char *Txt_View_public_profile;
extern const char *Txt_View_record_for_this_course;
extern const char *Txt_View_record_and_office_hours;
/***** Button to view user's public profile *****/
if (Pri_ShowingIsAllowed (Gbl.Usrs.Other.UsrDat.ProfileVisibility,
&Gbl.Usrs.Other.UsrDat))
Lay_PutContextualLink (ActSeePubPrf,
Usr_PutParamOtherUsrCodEncrypted,
"usr64x64.gif",
Txt_View_public_profile,NULL,
NULL);
/***** Button to view user's record card *****/
if (Usr_CheckIfICanViewRecordStd (&Gbl.Usrs.Other.UsrDat))
/* View student's records: common record card and course record card */
Lay_PutContextualLink (ActSeeRecOneStd,
Usr_PutParamOtherUsrCodEncrypted,
"card64x64.gif",
Txt_View_record_for_this_course,NULL,
NULL);
else if (Usr_CheckIfICanViewRecordTch (&Gbl.Usrs.Other.UsrDat))
Lay_PutContextualLink (ActSeeRecOneTch,
Usr_PutParamOtherUsrCodEncrypted,
"card64x64.gif",
Txt_View_record_and_office_hours,NULL,
NULL);
}
/*****************************************************************************/
/********************* Put button to create a new event **********************/
/*****************************************************************************/
static void Agd_PutButtonToCreateNewEvent (void)
{
extern const char *Txt_New_event;
Act_FormStart (ActFrmNewEvtMyAgd);
Agd_PutParamsToCreateNewEvent ();
Lay_PutConfirmButton (Txt_New_event);
Act_FormEnd ();
}
/*****************************************************************************/
/******************** Put parameters to create a new event *******************/
/*****************************************************************************/
static void Agd_PutParamsToCreateNewEvent (void)
{
Agd_PutHiddenParamEventsOrder ();
Pag_PutHiddenParamPagNum (Gbl.Pag.CurrentPage);
}
/*****************************************************************************/
/******************************* Show one event ******************************/
/*****************************************************************************/
static void Agd_ShowOneEvent (Agd_AgendaType_t AgendaType,long AgdCod)
{
extern const char *Dat_TimeStatusClassVisible[Dat_NUM_TIME_STATUS];
extern const char *Dat_TimeStatusClassHidden[Dat_NUM_TIME_STATUS];
extern const char *Txt_Today;
static unsigned UniqueId = 0;
struct AgendaEvent AgdEvent;
char Txt[Cns_MAX_BYTES_TEXT + 1];
/***** Get data of this event *****/
AgdEvent.AgdCod = AgdCod;
switch (AgendaType)
{
case Agd_MY_FULL_AGENDA_TODAY:
case Agd_MY_FULL_AGENDA:
case Agd_MY_PUBLIC_AGENDA_TODAY:
case Agd_MY_PUBLIC_AGENDA:
AgdEvent.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
break;
case Agd_OTHER_PUBLIC_AGENDA_TODAY:
case Agd_OTHER_PUBLIC_AGENDA:
AgdEvent.UsrCod = Gbl.Usrs.Other.UsrDat.UsrCod;
break;
}
Agd_GetDataOfEventByCod (&AgdEvent);
/***** Write first row of data of this event *****/
/* Start date/time */
UniqueId++;
fprintf (Gbl.F.Out,"<tr>"
"<td id=\"agd_date_start_%u\" class=\"%s LEFT_BOTTOM COLOR%u\">"
"<script type=\"text/javascript\">"
"writeLocalDateHMSFromUTC('agd_date_start_%u',"
"%ld,'<br />','%s',true,true,false);"
"</script>"
"</td>",
UniqueId,
AgdEvent.Hidden ? Dat_TimeStatusClassHidden[AgdEvent.TimeStatus] :
Dat_TimeStatusClassVisible[AgdEvent.TimeStatus],
Gbl.RowEvenOdd,
UniqueId,AgdEvent.TimeUTC[Agd_START_TIME],Txt_Today);
/* End date/time */
UniqueId++;
fprintf (Gbl.F.Out,"<td id=\"agd_date_end_%u\" class=\"%s LEFT_BOTTOM COLOR%u\">"
"<script type=\"text/javascript\">"
"writeLocalDateHMSFromUTC('agd_date_end_%u',"
"%ld,'<br />','%s',false,true,false);"
"</script>"
"</td>",
UniqueId,
AgdEvent.Hidden ? Dat_TimeStatusClassHidden[AgdEvent.TimeStatus] :
Dat_TimeStatusClassVisible[AgdEvent.TimeStatus],
Gbl.RowEvenOdd,
UniqueId,AgdEvent.TimeUTC[Agd_END_TIME],
Txt_Today);
/* Event */
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">"
"<div class=\"%s\">%s</div>"
"</td>",
Gbl.RowEvenOdd,
AgdEvent.Hidden ? "ASG_TITLE_LIGHT" :
"ASG_TITLE",
AgdEvent.Event);
/* Location */
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP COLOR%u\">"
"<div class=\"%s\">%s</div>"
"</td>"
"</tr>",
Gbl.RowEvenOdd,
AgdEvent.Hidden ? "ASG_TITLE_LIGHT" :
"ASG_TITLE",
AgdEvent.Location);
/***** Write second row of data of this event *****/
fprintf (Gbl.F.Out,"<tr>"
"<td colspan=\"2\" class=\"LEFT_TOP COLOR%u\">",
Gbl.RowEvenOdd);
/* Forms to remove/edit this event */
switch (AgendaType)
{
case Agd_MY_FULL_AGENDA_TODAY:
case Agd_MY_FULL_AGENDA:
Agd_PutFormsToRemEditOneEvent (&AgdEvent);
break;
default:
break;
}
fprintf (Gbl.F.Out,"</td>");
/* Text of the event */
Agd_GetEventTxtFromDB (&AgdEvent,Txt);
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
fprintf (Gbl.F.Out,"<td colspan=\"2\" class=\"LEFT_TOP COLOR%u\">"
"<p class=\"%s\">%s</p>"
"</td>"
"</tr>",
Gbl.RowEvenOdd,
AgdEvent.Hidden ? "DAT_LIGHT" :
"DAT",
Txt);
Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd;
}
/*****************************************************************************/
/********** Get parameter with the type or order in list of events ***********/
/*****************************************************************************/
static void Agd_GetParamEventOrder (void)
{
static bool AlreadyGot = false;
if (!AlreadyGot)
{
Gbl.Agenda.SelectedOrder = (Agd_Order_t)
Par_GetParToUnsignedLong ("Order",
0,
Agd_NUM_ORDERS - 1,
(unsigned long) Agd_ORDER_DEFAULT);
AlreadyGot = true;
}
}
/*****************************************************************************/
/****** Put a hidden parameter with the type of order in list of events ******/
/*****************************************************************************/
void Agd_PutHiddenParamEventsOrder (void)
{
Par_PutHiddenParamUnsigned ("Order",(unsigned) Gbl.Agenda.SelectedOrder);
}
/*****************************************************************************/
/******************* Put a link (form) to edit one event *********************/
/*****************************************************************************/
static void Agd_PutFormsToRemEditOneEvent (struct AgendaEvent *AgdEvent)
{
extern const char *Txt_Remove;
extern const char *Txt_Show;
extern const char *Txt_Hide;
extern const char *Txt_Event_private_click_to_make_it_visible_to_the_users_of_your_courses;
extern const char *Txt_Event_visible_to_the_users_of_your_courses_click_to_make_it_private;
extern const char *Txt_Edit;
Gbl.Agenda.AgdCodToEdit = AgdEvent->AgdCod; // Used as parameter in contextual links
/***** Put form to remove event *****/
Lay_PutContextualLink (ActReqRemEvtMyAgd,Agd_PutParams,
"remove-on64x64.png",
Txt_Remove,NULL,
NULL);
/***** Put form to hide/show event *****/
if (AgdEvent->Hidden)
Lay_PutContextualLink (ActShoEvtMyAgd,Agd_PutParams,
"eye-slash-on64x64.png",
Txt_Show,NULL,
NULL);
else
Lay_PutContextualLink (ActHidEvtMyAgd,Agd_PutParams,
"eye-on64x64.png",
Txt_Hide,NULL,
NULL);
/***** Put form to edit event *****/
Lay_PutContextualLink (ActEdiOneEvtMyAgd,Agd_PutParams,
"edit64x64.png",
Txt_Edit,NULL,
NULL);
/***** Put form to make event public/private *****/
if (AgdEvent->Public)
Lay_PutContextualLink (ActPrvEvtMyAgd,Agd_PutParams,
"unlock-on64x64.png",
Txt_Event_visible_to_the_users_of_your_courses_click_to_make_it_private,NULL,
NULL);
else
Lay_PutContextualLink (ActPubEvtMyAgd,Agd_PutParams,
"lock-on64x64.png",
Txt_Event_private_click_to_make_it_visible_to_the_users_of_your_courses,NULL,
NULL);
}
/*****************************************************************************/
/********************** Params used to edit an event *************************/
/*****************************************************************************/
static void Agd_PutParams (void)
{
Agd_PutParamAgdCod (Gbl.Agenda.AgdCodToEdit);
Agd_PutHiddenParamEventsOrder ();
Pag_PutHiddenParamPagNum (Gbl.Pag.CurrentPage);
}
/*****************************************************************************/
/************************* Get list of agenda events *************************/
/*****************************************************************************/
static void Agd_GetListEvents (Agd_AgendaType_t AgendaType)
{
char OrderBySubQuery[256];
char Query[1024];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
unsigned NumEvent;
if (Gbl.Agenda.LstIsRead)
Agd_FreeListEvents ();
/***** Get list of events from database *****/
switch (Gbl.Agenda.SelectedOrder)
{
case Agd_ORDER_BY_START_DATE:
sprintf (OrderBySubQuery,"StartTime,"
"EndTime,"
"Event,"
"Location");
break;
case Agd_ORDER_BY_END_DATE:
sprintf (OrderBySubQuery,"EndTime,"
"StartTime,"
"Event,"
"Location");
break;
}
switch (AgendaType)
{
case Agd_MY_FULL_AGENDA_TODAY:
sprintf (Query,"SELECT AgdCod FROM agendas"
" WHERE UsrCod='%ld'"
" AND DATE(StartTime)<=CURDATE()"
" AND DATE(EndTime)>=CURDATE()" // Only today events
" ORDER BY %s",
Gbl.Usrs.Me.UsrDat.UsrCod,OrderBySubQuery);
break;
case Agd_MY_FULL_AGENDA:
sprintf (Query,"SELECT AgdCod FROM agendas"
" WHERE UsrCod='%ld'"
" ORDER BY %s",
Gbl.Usrs.Me.UsrDat.UsrCod,OrderBySubQuery);
break;
case Agd_MY_PUBLIC_AGENDA_TODAY:
sprintf (Query,"SELECT AgdCod FROM agendas"
" WHERE UsrCod='%ld' AND Public='Y' AND Hidden='N'"
" AND DATE(StartTime)<=CURDATE()"
" AND DATE(EndTime)>=CURDATE()" // Only today events
" ORDER BY %s",
Gbl.Usrs.Me.UsrDat.UsrCod,OrderBySubQuery);
break;
case Agd_MY_PUBLIC_AGENDA:
sprintf (Query,"SELECT AgdCod FROM agendas"
" WHERE UsrCod='%ld' AND Public='Y' AND Hidden='N'"
" AND DATE(EndTime)>=CURDATE()" // Only today and future events
" ORDER BY %s",
Gbl.Usrs.Me.UsrDat.UsrCod,OrderBySubQuery);
break;
case Agd_OTHER_PUBLIC_AGENDA_TODAY:
sprintf (Query,"SELECT AgdCod FROM agendas"
" WHERE UsrCod='%ld' AND Public='Y' AND Hidden='N'"
" AND DATE(StartTime)<=CURDATE()"
" AND DATE(EndTime)>=CURDATE()" // Only today events
" ORDER BY %s",
Gbl.Usrs.Other.UsrDat.UsrCod,OrderBySubQuery);
break;
case Agd_OTHER_PUBLIC_AGENDA:
sprintf (Query,"SELECT AgdCod FROM agendas"
" WHERE UsrCod='%ld' AND Public='Y' AND Hidden='N'"
" AND DATE(EndTime)>=CURDATE()" // Only today and future events
" ORDER BY %s",
Gbl.Usrs.Other.UsrDat.UsrCod,OrderBySubQuery);
break;
}
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get agenda events");
if (NumRows) // Events found...
{
Gbl.Agenda.Num = (unsigned) NumRows;
/***** Create list of events *****/
if ((Gbl.Agenda.LstAgdCods = (long *) calloc (NumRows,sizeof (long))) == NULL)
Lay_ShowErrorAndExit ("Not enough memory to store list of agenda events.");
/***** Get the events codes *****/
for (NumEvent = 0;
NumEvent < Gbl.Agenda.Num;
NumEvent++)
{
/* Get next event code */
row = mysql_fetch_row (mysql_res);
if ((Gbl.Agenda.LstAgdCods[NumEvent] = Str_ConvertStrCodToLongCod (row[0])) < 0)
Lay_ShowErrorAndExit ("Error: wrong event code.");
}
}
else
Gbl.Agenda.Num = 0;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
Gbl.Agenda.LstIsRead = true;
}
/*****************************************************************************/
/*********************** Get event data using its code ***********************/
/*****************************************************************************/
static void Agd_GetDataOfEventByCod (struct AgendaEvent *AgdEvent)
{
char Query[512];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
/***** Build query *****/
sprintf (Query,"SELECT AgdCod,Public,Hidden,"
"UNIX_TIMESTAMP(StartTime),"
"UNIX_TIMESTAMP(EndTime),"
"NOW()>EndTime," // Past event?
"NOW()<StartTime," // Future event?
"Event,Location"
" FROM agendas"
" WHERE AgdCod='%ld' AND UsrCod='%ld'",
AgdEvent->AgdCod,AgdEvent->UsrCod);
/***** Get data of event from database *****/
if (DB_QuerySELECT (Query,&mysql_res,"can not get agenda event data")) // Event found...
{
/* Get row:
row[0] AgdCod
row[1] Public
row[2] Hidden
row[3] UNIX_TIMESTAMP(StartTime)
row[4] UNIX_TIMESTAMP(EndTime)
row[5] NOW()>EndTime // Past event?
row[6] NOW()<StartTime // Future event?
row[7] Event
row[8] Location
*/
row = mysql_fetch_row (mysql_res);
/* Get code of the event (row[0]) */
AgdEvent->AgdCod = Str_ConvertStrCodToLongCod (row[0]);
/* Get whether the event is public or not (row[1]) */
AgdEvent->Public = (row[1][0] == 'Y');
/* Get whether the event is hidden or not (row[2]) */
AgdEvent->Hidden = (row[2][0] == 'Y');
/* Get start date (row[3] holds the start UTC time) */
AgdEvent->TimeUTC[Agd_START_TIME] = Dat_GetUNIXTimeFromStr (row[3]);
/* Get end date (row[4] holds the end UTC time) */
AgdEvent->TimeUTC[Agd_END_TIME ] = Dat_GetUNIXTimeFromStr (row[4]);
/* Get whether the event is past, present or future (row(5), row[6]) */
AgdEvent->TimeStatus = ((row[5][0] == '1') ? Dat_PAST :
((row[6][0] == '1') ? Dat_FUTURE :
Dat_PRESENT));
/* Get the event (row[7]) */
Str_Copy (AgdEvent->Event,row[7],
Agd_MAX_LENGTH_EVENT);
/* Get the event (row[8]) */
Str_Copy (AgdEvent->Location,row[8],
Agd_MAX_LENGTH_LOCATION);
}
else
{
/***** Clear all event data *****/
AgdEvent->AgdCod = -1L;
AgdEvent->Public = false;
AgdEvent->Hidden = false;
AgdEvent->TimeUTC[Agd_START_TIME] =
AgdEvent->TimeUTC[Agd_END_TIME ] = (time_t) 0;
AgdEvent->TimeStatus = Dat_FUTURE;
AgdEvent->Event[0] = '\0';
AgdEvent->Location[0] = '\0';
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/*************************** Free list of events *****************************/
/*****************************************************************************/
void Agd_FreeListEvents (void)
{
if (Gbl.Agenda.LstIsRead && Gbl.Agenda.LstAgdCods)
{
/***** Free memory used by the list of events *****/
free ((void *) Gbl.Agenda.LstAgdCods);
Gbl.Agenda.LstAgdCods = NULL;
Gbl.Agenda.Num = 0;
Gbl.Agenda.LstIsRead = false;
}
}
/*****************************************************************************/
/*********************** Get event text from database ************************/
/*****************************************************************************/
static void Agd_GetEventTxtFromDB (struct AgendaEvent *AgdEvent,
char Txt[Cns_MAX_BYTES_TEXT + 1])
{
char Query[512];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
/***** Get text of event from database *****/
sprintf (Query,"SELECT Txt FROM agendas"
" WHERE AgdCod='%ld' AND UsrCod='%ld'",
AgdEvent->AgdCod,AgdEvent->UsrCod);
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get event text");
/***** The result of the query must have one row or none *****/
if (NumRows == 1)
{
/* Get info text */
row = mysql_fetch_row (mysql_res);
Str_Copy (Txt,row[0],
Cns_MAX_BYTES_TEXT);
}
else
Txt[0] = '\0';
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (NumRows > 1)
Lay_ShowErrorAndExit ("Error when getting event text.");
}
/*****************************************************************************/
/******************* Write parameter with code of event **********************/
/*****************************************************************************/
static void Agd_PutParamAgdCod (long AgdCod)
{
Par_PutHiddenParamLong ("AgdCod",AgdCod);
}
/*****************************************************************************/
/******************** Get parameter with code of event ***********************/
/*****************************************************************************/
long Agd_GetParamAgdCod (void)
{
/***** Get code of event *****/
return Par_GetParToLong ("AgdCod");
}
/*****************************************************************************/
/************** Ask for confirmation of removing of an event *****************/
/*****************************************************************************/
void Agd_AskRemEvent (void)
{
extern const char *Txt_Do_you_really_want_to_remove_the_event_X;
extern const char *Txt_Remove_event;
struct AgendaEvent AgdEvent;
/***** Get parameters *****/
Agd_GetParamEventOrder ();
Pag_GetParamPagNum (Pag_MY_FULL_AGENDA);
/***** Get event code *****/
if ((AgdEvent.AgdCod = Agd_GetParamAgdCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of event is missing.");
/***** Get data of the event from database *****/
AgdEvent.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
Agd_GetDataOfEventByCod (&AgdEvent);
/***** Button of confirmation of removing *****/
Act_FormStart (ActRemEvtMyAgd);
Agd_PutParamAgdCod (AgdEvent.AgdCod);
Agd_PutHiddenParamEventsOrder ();
Pag_PutHiddenParamPagNum (Gbl.Pag.CurrentPage);
/***** Ask for confirmation of removing *****/
sprintf (Gbl.Message,Txt_Do_you_really_want_to_remove_the_event_X,
AgdEvent.Event);
Lay_ShowAlert (Lay_WARNING,Gbl.Message);
Lay_PutRemoveButton (Txt_Remove_event);
Act_FormEnd ();
/***** Show events again *****/
Agd_ShowMyAgenda ();
}
/*****************************************************************************/
/****************************** Remove an event ******************************/
/*****************************************************************************/
void Agd_RemoveEvent (void)
{
extern const char *Txt_Event_X_removed;
char Query[512];
struct AgendaEvent AgdEvent;
/***** Get event code *****/
if ((AgdEvent.AgdCod = Agd_GetParamAgdCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of event is missing.");
/***** Get data of the event from database *****/
AgdEvent.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
Agd_GetDataOfEventByCod (&AgdEvent);
/***** Remove event *****/
sprintf (Query,"DELETE FROM agendas"
" WHERE AgdCod='%ld' AND UsrCod='%ld'",
AgdEvent.AgdCod,AgdEvent.UsrCod);
DB_QueryDELETE (Query,"can not remove event");
/***** Write message to show the change made *****/
sprintf (Gbl.Message,Txt_Event_X_removed,AgdEvent.Event);
Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
/***** Show events again *****/
Agd_ShowMyAgenda ();
}
/*****************************************************************************/
/********************************* Hide event ********************************/
/*****************************************************************************/
void Agd_HideEvent (void)
{
extern const char *Txt_Event_X_is_now_hidden;
char Query[512];
struct AgendaEvent AgdEvent;
/***** Get event code *****/
if ((AgdEvent.AgdCod = Agd_GetParamAgdCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of event is missing.");
/***** Get data of the event from database *****/
AgdEvent.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
Agd_GetDataOfEventByCod (&AgdEvent);
/***** Set event private *****/
sprintf (Query,"UPDATE agendas SET Hidden='Y'"
" WHERE AgdCod='%ld' AND UsrCod='%ld'",
AgdEvent.AgdCod,AgdEvent.UsrCod);
DB_QueryUPDATE (Query,"can not hide event");
/***** Write message to show the change made *****/
sprintf (Gbl.Message,Txt_Event_X_is_now_hidden,AgdEvent.Event);
Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
/***** Show events again *****/
Agd_ShowMyAgenda ();
}
/*****************************************************************************/
/****************************** Unhide event *********************************/
/*****************************************************************************/
void Agd_UnhideEvent (void)
{
extern const char *Txt_Event_X_is_now_visible;
char Query[256];
struct AgendaEvent AgdEvent;
/***** Get event code *****/
if ((AgdEvent.AgdCod = Agd_GetParamAgdCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of event is missing.");
/***** Get data of the event from database *****/
AgdEvent.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
Agd_GetDataOfEventByCod (&AgdEvent);
/***** Set event public *****/
sprintf (Query,"UPDATE agendas SET Hidden='N'"
" WHERE AgdCod='%ld' AND UsrCod='%ld'",
AgdEvent.AgdCod,AgdEvent.UsrCod);
DB_QueryUPDATE (Query,"can not show event");
/***** Write message to show the change made *****/
sprintf (Gbl.Message,Txt_Event_X_is_now_visible,
AgdEvent.Event);
Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
/***** Show events again *****/
Agd_ShowMyAgenda ();
}
/*****************************************************************************/
/****************************** Make event private ***************************/
/*****************************************************************************/
void Agd_MakeEventPrivate (void)
{
extern const char *Txt_Event_X_is_now_private;
char Query[512];
struct AgendaEvent AgdEvent;
/***** Get event code *****/
if ((AgdEvent.AgdCod = Agd_GetParamAgdCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of event is missing.");
/***** Get data of the event from database *****/
AgdEvent.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
Agd_GetDataOfEventByCod (&AgdEvent);
/***** Make event private *****/
sprintf (Query,"UPDATE agendas SET Public='N'"
" WHERE AgdCod='%ld' AND UsrCod='%ld'",
AgdEvent.AgdCod,AgdEvent.UsrCod);
DB_QueryUPDATE (Query,"can not make event private");
/***** Write message to show the change made *****/
sprintf (Gbl.Message,Txt_Event_X_is_now_private,AgdEvent.Event);
Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
/***** Show events again *****/
Agd_ShowMyAgenda ();
}
/*****************************************************************************/
/******** Make event public (make it visible to users of my courses) *********/
/*****************************************************************************/
void Agd_MakeEventPublic (void)
{
extern const char *Txt_Event_X_is_now_visible_to_users_of_your_courses;
char Query[256];
struct AgendaEvent AgdEvent;
/***** Get event code *****/
if ((AgdEvent.AgdCod = Agd_GetParamAgdCod ()) == -1L)
Lay_ShowErrorAndExit ("Code of event is missing.");
/***** Get data of the event from database *****/
AgdEvent.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
Agd_GetDataOfEventByCod (&AgdEvent);
/***** Make event public *****/
sprintf (Query,"UPDATE agendas SET Public='Y'"
" WHERE AgdCod='%ld' AND UsrCod='%ld'",
AgdEvent.AgdCod,AgdEvent.UsrCod);
DB_QueryUPDATE (Query,"can not make event public");
/***** Write message to show the change made *****/
sprintf (Gbl.Message,Txt_Event_X_is_now_visible_to_users_of_your_courses,
AgdEvent.Event);
Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
/***** Show events again *****/
Agd_ShowMyAgenda ();
}
/*****************************************************************************/
/******************** Put a form to create a new event ***********************/
/*****************************************************************************/
void Agd_RequestCreatOrEditEvent (void)
{
extern const char *Hlp_PROFILE_Agenda_new_event;
extern const char *Hlp_PROFILE_Agenda_edit_event;
extern const char *The_ClassForm[The_NUM_THEMES];
extern const char *Txt_New_event;
extern const char *Txt_Edit_event;
extern const char *Txt_Location;
extern const char *Txt_Event;
extern const char *Txt_Description;
extern const char *Txt_Create_event;
extern const char *Txt_Save;
struct AgendaEvent AgdEvent;
bool ItsANewEvent;
char Txt[Cns_MAX_BYTES_TEXT + 1];
/***** Get parameters *****/
Agd_GetParamEventOrder ();
Pag_GetParamPagNum (Pag_MY_FULL_AGENDA);
/***** Get the code of the event *****/
ItsANewEvent = ((AgdEvent.AgdCod = Agd_GetParamAgdCod ()) == -1L);
/***** Get from the database the data of the event *****/
AgdEvent.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
if (ItsANewEvent)
{
/* Initialize to empty event */
AgdEvent.AgdCod = -1L;
AgdEvent.TimeUTC[Agd_START_TIME] = Gbl.StartExecutionTimeUTC;
AgdEvent.TimeUTC[Agd_END_TIME ] = Gbl.StartExecutionTimeUTC + (2 * 60 * 60); // +2 hours
AgdEvent.TimeStatus = Dat_FUTURE;
AgdEvent.Event[0] = '\0';
AgdEvent.Location[0] = '\0';
}
else
{
/* Get data of the event from database */
Agd_GetDataOfEventByCod (&AgdEvent);
/* Get text of the event from database */
Agd_GetEventTxtFromDB (&AgdEvent,Txt);
}
/***** Start form *****/
if (ItsANewEvent)
Act_FormStart (ActNewEvtMyAgd);
else
{
Act_FormStart (ActChgEvtMyAgd);
Agd_PutParamAgdCod (AgdEvent.AgdCod);
}
Agd_PutHiddenParamEventsOrder ();
Pag_PutHiddenParamPagNum (Gbl.Pag.CurrentPage);
/***** Table start *****/
Lay_StartRoundFrameTable (NULL,
ItsANewEvent ? Txt_New_event :
Txt_Edit_event,
NULL,
ItsANewEvent ? Hlp_PROFILE_Agenda_new_event :
Hlp_PROFILE_Agenda_edit_event,
2);
/***** Event *****/
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"RIGHT_MIDDLE\">"
"<label for=\"Event\" class=\"%s\">%s:</label>"
"</td>"
"<td class=\"LEFT_MIDDLE\">"
"<input type=\"text\" id=\"Event\" name=\"Event\""
" size=\"45\" maxlength=\"%u\" value=\"%s\""
" required=\"required\" />"
"</td>"
"</tr>",
The_ClassForm[Gbl.Prefs.Theme],
Txt_Event,
Agd_MAX_LENGTH_EVENT,AgdEvent.Event);
/***** Location *****/
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"RIGHT_MIDDLE\">"
"<label for=\"Location\" class=\"%s\">%s:</label>"
"</td>"
"<td class=\"LEFT_MIDDLE\">"
"<input type=\"text\" id=\"Location\" name=\"Location\""
" size=\"45\" maxlength=\"%u\" value=\"%s\""
" required=\"required\" />"
"</td>"
"</tr>",
The_ClassForm[Gbl.Prefs.Theme],
Txt_Location,
Agd_MAX_LENGTH_LOCATION,AgdEvent.Location);
/***** Start and end dates *****/
Dat_PutFormStartEndClientLocalDateTimes (AgdEvent.TimeUTC,
Dat_FORM_SECONDS_OFF);
/***** Text *****/
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"RIGHT_TOP\">"
"<label for=\"Txt\" class=\"%s\">%s:</label>"
"</td>"
"<td class=\"LEFT_TOP\">"
"<textarea id=\"Txt\" name=\"Txt\""
" cols=\"60\" rows=\"10\">",
The_ClassForm[Gbl.Prefs.Theme],
Txt_Description);
if (!ItsANewEvent)
fprintf (Gbl.F.Out,"%s",Txt);
fprintf (Gbl.F.Out,"</textarea>"
"</td>"
"</tr>");
/***** New event *****/
if (ItsANewEvent)
Lay_EndRoundFrameTableWithButton (Lay_CREATE_BUTTON,Txt_Create_event);
else
Lay_EndRoundFrameTableWithButton (Lay_CONFIRM_BUTTON,Txt_Save);
Act_FormEnd ();
/***** Show current events, if any *****/
Agd_ShowMyAgenda ();
}
/*****************************************************************************/
/********************* Receive form to create a new event ********************/
/*****************************************************************************/
void Agd_RecFormEvent (void)
{
extern const char *Txt_Already_existed_an_event_with_the_title_X;
extern const char *Txt_You_must_specify_the_title_of_the_event;
extern const char *Txt_Created_new_event_X;
extern const char *Txt_The_event_has_been_modified;
struct AgendaEvent AgdEvent;
bool ItsANewEvent;
bool NewEventIsCorrect = true;
char Txt[Cns_MAX_BYTES_TEXT + 1];
/***** Set author of the event *****/
AgdEvent.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
/***** Get the code of the event *****/
ItsANewEvent = ((AgdEvent.AgdCod = Agd_GetParamAgdCod ()) == -1L);
/***** Get start/end date-times *****/
AgdEvent.TimeUTC[Agd_START_TIME] = Dat_GetTimeUTCFromForm ("StartTimeUTC");
AgdEvent.TimeUTC[Agd_END_TIME ] = Dat_GetTimeUTCFromForm ("EndTimeUTC" );
/***** Get event *****/
Par_GetParToText ("Location",AgdEvent.Location,Agd_MAX_LENGTH_LOCATION);
/***** Get event *****/
Par_GetParToText ("Event",AgdEvent.Event,Agd_MAX_LENGTH_EVENT);
/***** Get text *****/
Par_GetParToHTML ("Txt",Txt,Cns_MAX_BYTES_TEXT); // Store in HTML format (not rigorous)
/***** Adjust dates *****/
if (AgdEvent.TimeUTC[Agd_START_TIME] == 0)
AgdEvent.TimeUTC[Agd_START_TIME] = Gbl.StartExecutionTimeUTC;
if (AgdEvent.TimeUTC[Agd_END_TIME] == 0)
AgdEvent.TimeUTC[Agd_END_TIME] = AgdEvent.TimeUTC[Agd_START_TIME] + 2 * 60 * 60; // +2 hours
/***** Check if event is correct *****/
if (!AgdEvent.Location[0]) // If there is no event
{
NewEventIsCorrect = false;
Lay_ShowAlert (Lay_WARNING,Txt_You_must_specify_the_title_of_the_event);
}
/***** Check if event is correct *****/
if (AgdEvent.Event[0]) // If there's event
{
/* If title of event was in database... */
if (Agd_CheckIfSimilarEventExists (&AgdEvent))
{
NewEventIsCorrect = false;
sprintf (Gbl.Message,Txt_Already_existed_an_event_with_the_title_X,
AgdEvent.Event);
Lay_ShowAlert (Lay_WARNING,Gbl.Message);
}
}
else // If there is no event
{
NewEventIsCorrect = false;
Lay_ShowAlert (Lay_WARNING,Txt_You_must_specify_the_title_of_the_event);
}
/***** Create a new event or update an existing one *****/
if (NewEventIsCorrect)
{
if (ItsANewEvent)
{
Agd_CreateEvent (&AgdEvent,Txt); // Add new event to database
/***** Write success message *****/
sprintf (Gbl.Message,Txt_Created_new_event_X,AgdEvent.Event);
Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
}
else
{
Agd_UpdateEvent (&AgdEvent,Txt);
/***** Write success message *****/
Lay_ShowAlert (Lay_SUCCESS,Txt_The_event_has_been_modified);
}
/* Free memory for list of selected groups */
Grp_FreeListCodSelectedGrps ();
/***** Show events again *****/
Agd_ShowMyAgenda ();
}
else
// TODO: The form should be filled with partial data, now is always empty
Agd_RequestCreatOrEditEvent ();
}
/*****************************************************************************/
/*********** Check if the title or the folder of an event exists *************/
/*****************************************************************************/
static bool Agd_CheckIfSimilarEventExists (struct AgendaEvent *AgdEvent)
{
char Query[256 + Agd_MAX_LENGTH_EVENT];
/***** Get number of events with a field value from database *****/
sprintf (Query,"SELECT COUNT(*) FROM agendas"
" WHERE UsrCod='%ld' AND Event='%s' AND AgdCod<>'%ld'",
AgdEvent->UsrCod,AgdEvent->Event,AgdEvent->AgdCod);
return (DB_QueryCOUNT (Query,"can not get similar events") != 0);
}
/*****************************************************************************/
/************************** Create a new event *******************************/
/*****************************************************************************/
static void Agd_CreateEvent (struct AgendaEvent *AgdEvent,const char *Txt)
{
char Query[1024 + Cns_MAX_BYTES_TEXT];
/***** Create a new event *****/
sprintf (Query,"INSERT INTO agendas"
" (UsrCod,StartTime,EndTime,Event,Location,Txt)"
" VALUES"
" ('%ld',FROM_UNIXTIME('%ld'),FROM_UNIXTIME('%ld'),"
"'%s','%s','%s')",
AgdEvent->UsrCod,
AgdEvent->TimeUTC[Agd_START_TIME],
AgdEvent->TimeUTC[Agd_END_TIME ],
AgdEvent->Event,
AgdEvent->Location,
Txt);
AgdEvent->AgdCod = DB_QueryINSERTandReturnCode (Query,"can not create new event");
}
/*****************************************************************************/
/************************ Update an existing event ***************************/
/*****************************************************************************/
static void Agd_UpdateEvent (struct AgendaEvent *AgdEvent,const char *Txt)
{
char Query[1024 + Cns_MAX_BYTES_TEXT];
/***** Update the data of the event *****/
sprintf (Query,"UPDATE agendas SET "
"StartTime=FROM_UNIXTIME('%ld'),"
"EndTime=FROM_UNIXTIME('%ld'),"
"Event='%s',Location='%s',Txt='%s'"
" WHERE AgdCod='%ld' AND UsrCod='%ld'",
AgdEvent->TimeUTC[Agd_START_TIME],
AgdEvent->TimeUTC[Agd_END_TIME ],
AgdEvent->Event,AgdEvent->Location,Txt,
AgdEvent->AgdCod,AgdEvent->UsrCod);
DB_QueryUPDATE (Query,"can not update event");
}
/*****************************************************************************/
/********************** Remove all the events of a user **********************/
/*****************************************************************************/
void Agd_RemoveUsrEvents (long UsrCod)
{
char Query[128];
/***** Remove events *****/
sprintf (Query,"DELETE FROM agendas WHERE UsrCod='%ld'",UsrCod);
DB_QueryDELETE (Query,"can not remove all the events of a user");
}
/*****************************************************************************/
/********************* Get number of events from a user **********************/
/*****************************************************************************/
unsigned Agd_GetNumEventsFromUsr (long UsrCod)
{
char Query[128];
/***** Get number of events in a course from database *****/
sprintf (Query,"SELECT COUNT(*) FROM agendas WHERE UsrCod='%ld'",
UsrCod);
return (unsigned) DB_QueryCOUNT (Query,"can not get number of events from user");
}
/*****************************************************************************/
/********************** Get number of users with events **********************/
/*****************************************************************************/
// Returns the number of users with events in a given scope
unsigned Agd_GetNumUsrsWithEvents (Sco_Scope_t Scope)
{
char Query[1024];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumUsrs;
/***** Get number of courses with events from database *****/
switch (Scope)
{
case Sco_SCOPE_SYS:
sprintf (Query,"SELECT COUNT(DISTINCT UsrCod)"
" FROM agendas"
" WHERE UsrCod>'0'");
break;
case Sco_SCOPE_CTY:
sprintf (Query,"SELECT COUNT(DISTINCT agendas.UsrCod)"
" FROM institutions,centres,degrees,courses,crs_usr,agendas"
" WHERE institutions.CtyCod='%ld'"
" AND institutions.InsCod=centres.InsCod"
" AND centres.CtrCod=degrees.CtrCod"
" AND degrees.DegCod=courses.DegCod"
" AND courses.Status=0"
" AND courses.CrsCod=crs_usr.CrsCod"
" AND crs_usr.UsrCod=agendas.UsrCod",
Gbl.CurrentCty.Cty.CtyCod);
break;
case Sco_SCOPE_INS:
sprintf (Query,"SELECT COUNT(DISTINCT agendas.UsrCod)"
" FROM centres,degrees,courses,crs_usr,agendas"
" WHERE centres.InsCod='%ld'"
" AND centres.CtrCod=degrees.CtrCod"
" AND degrees.DegCod=courses.DegCod"
" AND courses.Status=0"
" AND courses.CrsCod=crs_usr.CrsCod"
" AND crs_usr.UsrCod=agendas.UsrCod",
Gbl.CurrentIns.Ins.InsCod);
break;
case Sco_SCOPE_CTR:
sprintf (Query,"SELECT COUNT(DISTINCT agendas.UsrCod)"
" FROM degrees,courses,crs_usr,agendas"
" WHERE degrees.CtrCod='%ld'"
" AND degrees.DegCod=courses.DegCod"
" AND courses.Status=0"
" AND courses.CrsCod=crs_usr.CrsCod"
" AND crs_usr.UsrCod=agendas.UsrCod",
Gbl.CurrentCtr.Ctr.CtrCod);
break;
case Sco_SCOPE_DEG:
sprintf (Query,"SELECT COUNT(DISTINCT agendas.UsrCod)"
" FROM courses,crs_usr,agendas"
" WHERE courses.DegCod='%ld'"
" AND courses.Status=0"
" AND courses.CrsCod=crs_usr.CrsCod"
" AND crs_usr.UsrCod=agendas.UsrCod",
Gbl.CurrentDeg.Deg.DegCod);
break;
case Sco_SCOPE_CRS:
sprintf (Query,"SELECT COUNT(DISTINCT agendas.UsrCod)"
" FROM crs_usr,agendas"
" WHERE crs_usr.CrsCod='%ld'"
" AND crs_usr.UsrCod=agendas.UsrCod",
Gbl.CurrentCrs.Crs.CrsCod);
break;
default:
Lay_ShowErrorAndExit ("Wrong scope.");
break;
}
DB_QuerySELECT (Query,&mysql_res,"can not get number of users with events");
/***** Get number of users *****/
row = mysql_fetch_row (mysql_res);
if (sscanf (row[0],"%u",&NumUsrs) != 1)
Lay_ShowErrorAndExit ("Error when getting number of users with events.");
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return NumUsrs;
}
/*****************************************************************************/
/*************************** Get number of events ****************************/
/*****************************************************************************/
// Returns the number of events in a given scope
unsigned Agd_GetNumEvents (Sco_Scope_t Scope)
{
char Query[1024];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumEvents;
/***** Get number of events from database *****/
switch (Scope)
{
case Sco_SCOPE_SYS:
sprintf (Query,"SELECT COUNT(*)"
" FROM agendas"
" WHERE UsrCod>'0'");
break;
case Sco_SCOPE_CTY:
sprintf (Query,"SELECT COUNT(*)"
" FROM institutions,centres,degrees,courses,crs_usr,agendas"
" WHERE institutions.CtyCod='%ld'"
" AND institutions.InsCod=centres.InsCod"
" AND centres.CtrCod=degrees.CtrCod"
" AND degrees.DegCod=courses.DegCod"
" AND courses.CrsCod=crs_usr.CrsCod"
" AND crs_usr.UsrCod=agendas.UsrCod",
Gbl.CurrentCty.Cty.CtyCod);
break;
case Sco_SCOPE_INS:
sprintf (Query,"SELECT COUNT(*)"
" FROM centres,degrees,courses,crs_usr,agendas"
" WHERE centres.InsCod='%ld'"
" AND centres.CtrCod=degrees.CtrCod"
" AND degrees.DegCod=courses.DegCod"
" AND courses.CrsCod=crs_usr.CrsCod"
" AND crs_usr.UsrCod=agendas.UsrCod",
Gbl.CurrentIns.Ins.InsCod);
break;
case Sco_SCOPE_CTR:
sprintf (Query,"SELECT COUNT(*)"
" FROM degrees,courses,crs_usr,agendas"
" WHERE degrees.CtrCod='%ld'"
" AND degrees.DegCod=courses.DegCod"
" AND courses.CrsCod=crs_usr.CrsCod"
" AND crs_usr.UsrCod=agendas.UsrCod",
Gbl.CurrentCtr.Ctr.CtrCod);
break;
case Sco_SCOPE_DEG:
sprintf (Query,"SELECT COUNT(*)"
" FROM courses,crs_usr,agendas"
" WHERE courses.DegCod='%ld'"
" AND courses.CrsCod=crs_usr.CrsCod"
" AND crs_usr.UsrCod=agendas.UsrCod",
Gbl.CurrentDeg.Deg.DegCod);
break;
case Sco_SCOPE_CRS:
sprintf (Query,"SELECT COUNT(*)"
" FROM crs_usr,agendas"
" WHERE crs_usr.CrsCod='%ld'"
" AND crs_usr.UsrCod=agendas.UsrCod",
Gbl.CurrentCrs.Crs.CrsCod);
break;
default:
Lay_ShowErrorAndExit ("Wrong scope.");
break;
}
DB_QuerySELECT (Query,&mysql_res,"can not get number of events");
/***** Get number of events *****/
row = mysql_fetch_row (mysql_res);
if (sscanf (row[0],"%u",&NumEvents) != 1)
Lay_ShowErrorAndExit ("Error when getting number of events.");
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return NumEvents;
}
/*****************************************************************************/
/************************** Show an agenda QR code ***************************/
/*****************************************************************************/
void Agd_PrintAgdQRCode (void)
{
extern const char *Txt_Where_s_USER;
/***** Start frame *****/
sprintf (Gbl.Title,Txt_Where_s_USER,Gbl.Usrs.Me.UsrDat.FullName);
Lay_StartRoundFrame (NULL,Gbl.Title,NULL,NULL);
/***** Print QR code ****/
QR_PrintQRCode ();
/***** End frame *****/
Lay_EndRoundFrame ();
}