swad-core/swad_notification.c

1883 lines
67 KiB
C
Raw Normal View History

2016-11-16 23:19:52 +01:00
// swad_notification.c: notifications about events, sent by email
2014-12-01 23:55:08 +01:00
/*
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-2023 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 ***********************************/
/*****************************************************************************/
#define _GNU_SOURCE // For asprintf
2019-12-29 12:39:00 +01:00
#include <stddef.h> // For NULL
#include <stdio.h> // For asprintf
2014-12-01 23:55:08 +01:00
#include <stdlib.h> // For system
#include <string.h>
#include <sys/wait.h> // For the macro WEXITSTATUS
#include <unistd.h> // For unlink
#include "swad_action.h"
#include "swad_action_list.h"
#include "swad_admin_database.h"
#include "swad_assignment_database.h"
2017-06-10 21:38:10 +02:00
#include "swad_box.h"
#include "swad_browser_database.h"
#include "swad_call_for_exam.h"
2014-12-01 23:55:08 +01:00
#include "swad_config.h"
#include "swad_config.h"
#include "swad_database.h"
2017-03-30 11:20:06 +02:00
#include "swad_enrolment.h"
#include "swad_enrolment_database.h"
#include "swad_error.h"
2020-04-14 17:15:17 +02:00
#include "swad_figure.h"
2015-03-24 00:01:40 +01:00
#include "swad_follow.h"
2018-11-09 20:47:39 +01:00
#include "swad_form.h"
2020-04-07 03:01:41 +02:00
#include "swad_forum.h"
#include "swad_forum_database.h"
2014-12-01 23:55:08 +01:00
#include "swad_global.h"
#include "swad_group_database.h"
2021-02-11 23:27:48 +01:00
#include "swad_hierarchy.h"
#include "swad_hierarchy_level.h"
2019-10-23 19:05:05 +02:00
#include "swad_HTML.h"
2014-12-01 23:55:08 +01:00
#include "swad_mark.h"
2020-04-14 17:15:17 +02:00
#include "swad_message.h"
#include "swad_message_database.h"
2014-12-01 23:55:08 +01:00
#include "swad_notice.h"
#include "swad_notification.h"
#include "swad_notification_database.h"
#include "swad_parameter_code.h"
#include "swad_setting.h"
#include "swad_setting_database.h"
2020-04-14 17:15:17 +02:00
#include "swad_survey.h"
#include "swad_survey_database.h"
2019-03-12 21:25:55 +01:00
#include "swad_timeline.h"
#include "swad_timeline_database.h"
2021-02-11 17:45:16 +01:00
#include "swad_timeline_notification.h"
2021-02-11 13:10:08 +01:00
#include "swad_timeline_publication.h"
#include "swad_user_database.h"
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
2017-03-07 19:55:29 +01:00
// strings are limited to Ntf_MAX_BYTES_NOTIFY_EVENT characters
2017-01-15 18:02:52 +01:00
2014-12-01 23:55:08 +01:00
const char *Ntf_WSNotifyEvents[Ntf_NUM_NOTIFY_EVENTS] =
{
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_UNKNOWN ] = "unknown",
/* Start tab */
[Ntf_EVENT_TML_COMMENT ] = "timelineComment",
[Ntf_EVENT_TML_FAV ] = "timelineFav",
[Ntf_EVENT_TML_SHARE ] = "timelineShare",
[Ntf_EVENT_TML_MENTION ] = "timelineMention",
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_FOLLOWER ] = "follower",
/* System tab */
/* Country tab */
/* Institution tab */
/* Center tab */
2019-11-20 01:47:22 +01:00
/* Degree tab */
2014-12-01 23:55:08 +01:00
/* Course tab */
/* Assessment tab */
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_ASSIGNMENT ] = "assignment",
[Ntf_EVENT_CALL_FOR_EXAM ] = "examAnnouncement",
2019-11-20 01:47:22 +01:00
/* Files tab */
[Ntf_EVENT_DOCUMENT_FILE ] = "documentFile",
[Ntf_EVENT_TEACHERS_FILE ] = "teachersFile",
[Ntf_EVENT_SHARED_FILE ] = "sharedFile",
[Ntf_EVENT_MARKS_FILE ] = "marksFile",
2016-01-22 01:47:28 +01:00
/* Users tab */
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_ENROLMENT_STD ] = "enrollmentStudent",
[Ntf_EVENT_ENROLMENT_NET ] = "enrolmentNonEditingTeacher",
[Ntf_EVENT_ENROLMENT_TCH ] = "enrollmentTeacher",
[Ntf_EVENT_ENROLMENT_REQUEST] = "enrollmentRequest",
2014-12-01 23:55:08 +01:00
/* Messages tab */
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_NOTICE ] = "notice",
[Ntf_EVENT_FORUM_POST_COURSE] = "forumPostCourse",
[Ntf_EVENT_FORUM_REPLY ] = "forumReply",
[Ntf_EVENT_MESSAGE ] = "message",
/* Analytics tab */
[Ntf_EVENT_SURVEY ] = "survey",
2015-03-24 00:01:40 +01:00
/* Profile tab */
2014-12-01 23:55:08 +01:00
};
static const Act_Action_t Ntf_DefaultActions[Ntf_NUM_NOTIFY_EVENTS] =
{
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_UNKNOWN ] = ActUnk,
/* Start tab */
[Ntf_EVENT_TML_COMMENT ] = ActSeeGblTL,
[Ntf_EVENT_TML_FAV ] = ActSeeGblTL,
[Ntf_EVENT_TML_SHARE ] = ActSeeGblTL,
[Ntf_EVENT_TML_MENTION ] = ActSeeGblTL,
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_FOLLOWER ] = ActSeeFlr,
/* System tab */
/* Country tab */
/* Institution tab */
/* Center tab */
2019-11-20 01:47:22 +01:00
/* Degree tab */
2014-12-01 23:55:08 +01:00
/* Course tab */
/* Assessment tab */
[Ntf_EVENT_ASSIGNMENT ] = ActSeeAllAsg,
[Ntf_EVENT_CALL_FOR_EXAM ] = ActSeeAllCfe,
2019-11-20 01:47:22 +01:00
/* Files tab */
[Ntf_EVENT_DOCUMENT_FILE ] = ActSeeAdmDocCrsGrp,
[Ntf_EVENT_TEACHERS_FILE ] = ActAdmTchCrsGrp,
[Ntf_EVENT_SHARED_FILE ] = ActAdmShaCrsGrp,
[Ntf_EVENT_MARKS_FILE ] = ActSeeAdmMrk,
2014-12-01 23:55:08 +01:00
/* Users tab */
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_ENROLMENT_STD ] = ActReqAccEnrStd,
[Ntf_EVENT_ENROLMENT_NET ] = ActReqAccEnrNET,
[Ntf_EVENT_ENROLMENT_TCH ] = ActReqAccEnrTch,
[Ntf_EVENT_ENROLMENT_REQUEST] = ActSeeSignUpReq,
2014-12-01 23:55:08 +01:00
/* Messages tab */
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_NOTICE ] = ActSeeOneNot,
[Ntf_EVENT_FORUM_POST_COURSE] = ActSeeFor,
[Ntf_EVENT_FORUM_REPLY ] = ActSeeFor,
[Ntf_EVENT_MESSAGE ] = ActExpRcvMsg,
/* Analytics tab */
[Ntf_EVENT_SURVEY ] = ActSeeAllSvy,
2015-03-24 00:01:40 +01:00
/* Profile tab */
2014-12-01 23:55:08 +01:00
};
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
// Notify me notification events
static const char *Ntf_ParNotifMeAboutNotifyEvents[Ntf_NUM_NOTIFY_EVENTS] =
2014-12-01 23:55:08 +01:00
{
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_UNKNOWN ] = "NotifyNtfEventUnknown",
/* Start tab */
[Ntf_EVENT_TML_COMMENT ] = "NotifyNtfEventTimelineComment",
[Ntf_EVENT_TML_FAV ] = "NotifyNtfEventTimelineFav",
[Ntf_EVENT_TML_SHARE ] = "NotifyNtfEventTimelineShare",
[Ntf_EVENT_TML_MENTION ] = "NotifyNtfEventTimelineMention",
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_FOLLOWER ] = "NotifyNtfEventFollower",
/* System tab */
/* Country tab */
/* Institution tab */
/* Center tab */
2019-11-20 01:47:22 +01:00
/* Degree tab */
2014-12-01 23:55:08 +01:00
/* Course tab */
/* Assessment tab */
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_ASSIGNMENT ] = "NotifyNtfEventAssignment",
[Ntf_EVENT_CALL_FOR_EXAM ] = "NotifyNtfEventExamAnnouncement",
2019-11-20 01:47:22 +01:00
/* Files tab */
[Ntf_EVENT_DOCUMENT_FILE ] = "NotifyNtfEventDocumentFile",
[Ntf_EVENT_TEACHERS_FILE ] = "NotifyNtfEventTeachersFile",
[Ntf_EVENT_SHARED_FILE ] = "NotifyNtfEventSharedFile",
[Ntf_EVENT_MARKS_FILE ] = "NotifyNtfEventMarksFile",
2014-12-01 23:55:08 +01:00
/* Messages tab */
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_NOTICE ] = "NotifyNtfEventNotice",
[Ntf_EVENT_FORUM_POST_COURSE] = "NotifyNtfEventForumPostCourse",
[Ntf_EVENT_FORUM_REPLY ] = "NotifyNtfEventForumReply",
[Ntf_EVENT_MESSAGE ] = "NotifyNtfEventMessage",
/* Users tab */
[Ntf_EVENT_ENROLMENT_STD ] = "NotifyNtfEventEnrolmentStudent",
[Ntf_EVENT_ENROLMENT_NET ] = "NotifyNtfEventEnrolmentNonEditingTeacher",
[Ntf_EVENT_ENROLMENT_TCH ] = "NotifyNtfEventEnrolmentTeacher",
[Ntf_EVENT_ENROLMENT_REQUEST] = "NotifyNtfEventEnrolmentRequest",
/* Analytics tab */
[Ntf_EVENT_SURVEY ] = "NotifyNtfEventSurvey",
2019-11-20 01:47:22 +01:00
/* Profile tab */
2014-12-01 23:55:08 +01:00
};
// Email me about notification events
static const char *Ntf_ParEmailMeAboutNotifyEvents[Ntf_NUM_NOTIFY_EVENTS] =
2014-12-01 23:55:08 +01:00
{
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_UNKNOWN ] = "EmailNtfEventUnknown",
/* Start tab */
[Ntf_EVENT_TML_COMMENT ] = "EmailNtfEventTimelineComment",
[Ntf_EVENT_TML_FAV ] = "EmailNtfEventTimelineFav",
[Ntf_EVENT_TML_SHARE ] = "EmailNtfEventTimelineShare",
[Ntf_EVENT_TML_MENTION ] = "EmailNtfEventTimelineMention",
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_FOLLOWER ] = "EmailNtfEventSocialFollower",
/* System tab */
/* Country tab */
/* Institution tab */
/* Center tab */
2019-11-20 01:47:22 +01:00
/* Degree tab */
2014-12-01 23:55:08 +01:00
/* Course tab */
/* Assessment tab */
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_ASSIGNMENT ] = "EmailNtfEventAssignment",
[Ntf_EVENT_CALL_FOR_EXAM ] = "EmailNtfEventExamAnnouncement",
2019-11-20 01:47:22 +01:00
/* Files tab */
[Ntf_EVENT_DOCUMENT_FILE ] = "EmailNtfEventDocumentFile",
[Ntf_EVENT_TEACHERS_FILE ] = "EmailNtfEventTeachersFile",
[Ntf_EVENT_SHARED_FILE ] = "EmailNtfEventSharedFile",
[Ntf_EVENT_MARKS_FILE ] = "EmailNtfEventMarksFile",
2014-12-01 23:55:08 +01:00
/* Messages tab */
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_NOTICE ] = "EmailNtfEventNotice",
[Ntf_EVENT_FORUM_POST_COURSE] = "EmailNtfEventForumPostCourse",
[Ntf_EVENT_FORUM_REPLY ] = "EmailNtfEventForumReply",
[Ntf_EVENT_MESSAGE ] = "EmailNtfEventMessage",
/* Users tab */
[Ntf_EVENT_ENROLMENT_STD ] = "EmailNtfEventEnrolmentStudent",
[Ntf_EVENT_ENROLMENT_NET ] = "EmailNtfEventEnrolmentNonEditingTeacher",
[Ntf_EVENT_ENROLMENT_TCH ] = "EmailNtfEventEnrolmentTeacher",
[Ntf_EVENT_ENROLMENT_REQUEST] = "EmailNtfEventEnrolmentRequest",
2019-11-21 11:39:30 +01:00
/* Analytics tab */
[Ntf_EVENT_SURVEY ] = "EmailNtfEventSurvey",
2015-03-24 00:01:40 +01:00
/* Profile tab */
2014-12-01 23:55:08 +01:00
};
// Icons for notification events
static const char *Ntf_Icons[Ntf_NUM_NOTIFY_EVENTS] =
{
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_UNKNOWN ] = "question.svg",
/* Start tab */
[Ntf_EVENT_TML_COMMENT ] = "comment-dots.svg",
[Ntf_EVENT_TML_FAV ] = "star.svg",
[Ntf_EVENT_TML_SHARE ] = "share-alt.svg",
[Ntf_EVENT_TML_MENTION ] = "at.svg",
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_FOLLOWER ] = "user-plus.svg",
/* System tab */
/* Country tab */
/* Institution tab */
/* Center tab */
2019-11-20 01:47:22 +01:00
/* Degree tab */
2014-12-01 23:55:08 +01:00
/* Course tab */
/* Assessment tab */
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_ASSIGNMENT ] = "edit.svg",
[Ntf_EVENT_CALL_FOR_EXAM ] = "bullhorn.svg",
2019-11-20 01:47:22 +01:00
/* Files tab */
[Ntf_EVENT_DOCUMENT_FILE ] = "file.svg",
[Ntf_EVENT_TEACHERS_FILE ] = "file.svg",
[Ntf_EVENT_SHARED_FILE ] = "file.svg",
[Ntf_EVENT_MARKS_FILE ] = "clipboard-list.svg",
2016-01-22 01:47:28 +01:00
/* Messages tab */
2019-11-20 01:47:22 +01:00
[Ntf_EVENT_NOTICE ] = "sticky-note.svg",
[Ntf_EVENT_FORUM_POST_COURSE] = "comments.svg",
[Ntf_EVENT_FORUM_REPLY ] = "comments.svg",
[Ntf_EVENT_MESSAGE ] = "envelope.svg",
/* Users tab */
[Ntf_EVENT_ENROLMENT_STD ] = "user.svg",
[Ntf_EVENT_ENROLMENT_NET ] = "user-tie.svg",
[Ntf_EVENT_ENROLMENT_TCH ] = "user-tie.svg",
[Ntf_EVENT_ENROLMENT_REQUEST] = "hand-point-up.svg",
2019-11-21 11:39:30 +01:00
/* Analytics tab */
[Ntf_EVENT_SURVEY ] = "poll.svg",
2015-03-24 00:01:40 +01:00
/* Profile tab */
2014-12-01 23:55:08 +01:00
};
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
2020-04-08 03:41:05 +02:00
static void Ntf_PutIconsNotif (__attribute__((unused)) void *Args);
2016-11-07 14:24:44 +01:00
2014-12-01 23:55:08 +01:00
static void Ntf_WriteFormAllNotifications (bool AllNotifications);
static bool Ntf_GetAllNotificationsFromForm (void);
2016-01-25 14:40:57 +01:00
static Act_Action_t Ntf_StartFormGoToAction (Ntf_NotifyEvent_t NotifyEvent,
long CrsCod,struct Usr_Data *UsrDat,long Cod,
const struct For_Forums *Forums);
static void Ntf_PutParNotifyEvent (Ntf_NotifyEvent_t NotifyEvent);
2016-01-25 14:40:57 +01:00
static void Ntf_SendPendingNotifByEMailToOneUsr (const struct Usr_Data *ToUsrDat,
unsigned *NumNotif,
unsigned *NumMails);
2014-12-01 23:55:08 +01:00
static void Ntf_GetNumNotifSent (long DegCod,long CrsCod,
Ntf_NotifyEvent_t NotifyEvent,
unsigned *NumEvents,unsigned *NumMails);
static void Ntf_UpdateNumNotifSent (long DegCod,long CrsCod,
Ntf_NotifyEvent_t NotifyEvent,
unsigned NumEvents,unsigned NumMails);
2016-11-07 14:12:15 +01:00
static void Ntf_GetParsNotifyEvents (void);
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/*************************** Show my notifications ***************************/
/*****************************************************************************/
void Ntf_ShowMyNotifications (void)
{
2019-03-12 21:25:55 +01:00
extern const char *Hlp_START_Notifications;
2019-01-10 03:04:30 +01:00
extern const char *Txt_Settings;
2017-03-24 19:27:45 +01:00
extern const char *Txt_Domains;
2016-11-22 10:19:10 +01:00
extern const char *Txt_Mark_all_NOTIFICATIONS_as_read;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Notifications;
extern const char *Txt_Date;
extern const char *Txt_Event;
extern const char *Txt_Location;
extern const char *Txt_MSG_From;
extern const char *Txt_Email;
extern const char *Txt_NOTIFY_EVENTS_SINGULAR[Ntf_NUM_NOTIFY_EVENTS];
extern const char *Txt_Forum;
extern const char *Txt_Course;
extern const char *Txt_Degree;
extern const char *Txt_Center;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Institution;
extern const char *Txt_NOTIFICATION_STATUS[Ntf_NUM_STATUS_TXT];
2016-11-26 17:40:48 +01:00
extern const char *Txt_You_have_no_notifications;
extern const char *Txt_You_have_no_unread_notifications;
2014-12-01 23:55:08 +01:00
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumNotif;
unsigned NumNotifications;
2014-12-01 23:55:08 +01:00
bool AllNotifications;
Ntf_NotifyEvent_t NotifyEvent = (Ntf_NotifyEvent_t) 0; // Initialized to avoid warning
struct Usr_Data UsrDat;
2021-02-11 23:27:48 +01:00
struct Hie_Hierarchy Hie;
2014-12-01 23:55:08 +01:00
long Cod;
2020-04-07 03:01:41 +02:00
struct For_Forums Forums;
2017-01-13 10:49:56 +01:00
char ForumName[For_MAX_BYTES_FORUM_NAME + 1];
2015-10-24 20:12:03 +02:00
time_t DateTimeUTC; // Date-time of the event
2014-12-01 23:55:08 +01:00
Ntf_Status_t Status;
Ntf_StatusTxt_t StatusTxt;
2017-03-08 14:12:33 +01:00
char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1];
2014-12-01 23:55:08 +01:00
char *ContentStr;
const char *ClassTxt;
2019-11-18 17:59:02 +01:00
const char *ClassLink;
const char *ClassAuthor;
const char *ClassBg;
2014-12-01 23:55:08 +01:00
bool PutLink;
Act_Action_t Action = ActUnk;
2014-12-01 23:55:08 +01:00
/***** Get my notifications from database *****/
AllNotifications = Ntf_GetAllNotificationsFromForm ();
NumNotifications = Ntf_DB_GetMyNotifications (&mysql_res,AllNotifications);
2014-12-01 23:55:08 +01:00
2019-10-24 09:46:20 +02:00
/***** Contextual menu *****/
Mnu_ContextMenuBegin ();
Ntf_WriteFormAllNotifications (AllNotifications); // Show all notifications
if (NumNotifications) // TODO: Show message only when I don't have notificacions at all
Lay_PutContextualLinkIconText (ActMrkNtfSee,NULL,
NULL,NULL,
"eye.svg",Ico_BLACK,
Txt_Mark_all_NOTIFICATIONS_as_read,NULL); // Mark notifications as read
Lay_PutContextualLinkIconText (ActReqEdiSet,Ntf_NOTIFICATIONS_ID,
NULL,NULL,
"cog.svg",Ico_BLACK,
Txt_Settings,NULL); // Change notification settings
Lay_PutContextualLinkIconText (ActSeeMai,NULL,
NULL,NULL,
"envelope.svg",Ico_BLACK,
Txt_Domains,NULL); // View allowed mail domains
2019-10-24 09:46:20 +02:00
Mnu_ContextMenuEnd ();
2014-12-01 23:55:08 +01:00
2019-10-26 02:19:42 +02:00
/***** Begin box *****/
2020-03-26 02:54:30 +01:00
Box_BoxBegin (NULL,Txt_Notifications,
2020-04-08 03:41:05 +02:00
Ntf_PutIconsNotif,NULL,
2019-03-12 21:25:55 +01:00
Hlp_START_Notifications,Box_NOT_CLOSABLE);
2016-11-26 17:40:48 +01:00
/***** List my notifications *****/
if (NumNotifications) // Notifications found
2014-12-01 23:55:08 +01:00
{
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
/***** Begin table *****/
HTM_TABLE_BeginWideMarginPadding (2);
/***** Heading *****/
HTM_TR_Begin (NULL);
HTM_TH_Span (Txt_Event ,HTM_HEAD_LEFT ,1,2,NULL);
HTM_TH (Txt_MSG_From,HTM_HEAD_LEFT );
HTM_TH (Txt_Location,HTM_HEAD_LEFT );
HTM_TH (Txt_Date ,HTM_HEAD_CENTER);
HTM_TH (Txt_Email ,HTM_HEAD_LEFT );
HTM_TR_End ();
/***** List notifications one by one *****/
for (NumNotif = 0;
NumNotif < NumNotifications;
NumNotif++)
{
/***** Get next notification *****/
row = mysql_fetch_row (mysql_res);
2014-12-01 23:55:08 +01:00
/* Get event type (row[0]) */
NotifyEvent = Ntf_GetNotifyEventFromStr (row[0]);
2014-12-01 23:55:08 +01:00
/* Get (from) user code (row[1]) */
UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[1]);
Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat, // Get user's data from database
Usr_DONT_GET_PREFS,
Usr_DONT_GET_ROLE_IN_CURRENT_CRS);
2014-12-01 23:55:08 +01:00
/* Get institution code (row[2]) */
Hie.Ins.InsCod = Str_ConvertStrCodToLongCod (row[2]);
Ins_GetInstitDataByCod (&Hie.Ins);
2014-12-01 23:55:08 +01:00
/* Get center code (row[3]) */
Hie.Ctr.CtrCod = Str_ConvertStrCodToLongCod (row[3]);
Ctr_GetCenterDataByCod (&Hie.Ctr);
2019-10-09 17:38:50 +02:00
/* Get degree code (row[4]) */
Hie.Deg.DegCod = Str_ConvertStrCodToLongCod (row[4]);
Deg_GetDegreeDataByCod (&Hie.Deg);
2016-01-03 01:13:57 +01:00
/* Get course code (row[5]) */
Hie.Crs.CrsCod = Str_ConvertStrCodToLongCod (row[5]);
Crs_GetCourseDataByCod (&Hie.Crs);
2014-12-01 23:55:08 +01:00
/* Get message/post/... code (row[6]) */
Cod = Str_ConvertStrCodToLongCod (row[6]);
2014-12-01 23:55:08 +01:00
/* Get forum type of the post */
if (NotifyEvent == Ntf_EVENT_FORUM_POST_COURSE ||
NotifyEvent == Ntf_EVENT_FORUM_REPLY)
{
For_ResetForums (&Forums);
For_GetThreadForumTypeAndHieCodOfAPost (Cod,&Forums.Forum);
For_SetForumName (&Forums.Forum,
ForumName,Gbl.Prefs.Language,false); // Set forum name in recipient's language
}
2014-12-01 23:55:08 +01:00
/* Get time of the event (row[7]) */
DateTimeUTC = Dat_GetUNIXTimeFromStr (row[7]);
2014-12-01 23:55:08 +01:00
/* Get status (row[8]) */
if (sscanf (row[8],"%u",&Status) != 1)
Err_WrongStatusExit ();
StatusTxt = Ntf_GetStatusTxtFromStatusBits (Status);
2019-10-07 17:36:41 +02:00
if (Status & Ntf_STATUS_BIT_REMOVED) // The source of the notification was removed
{
ClassTxt = "MSG_TIT_REM";
ClassLink = "BT_LINK MSG_TIT_REM";
ClassAuthor = "MSG_AUT_LIGHT";
ClassBg = "MSG_BG_REM";
PutLink = false;
}
else if (Status & Ntf_STATUS_BIT_READ) // I have already seen the source of the notification
{
ClassTxt = "MSG_TIT";
ClassLink = "LT BT_LINK MSG_TIT";
ClassAuthor = "MSG_AUT";
ClassBg = "MSG_BG";
PutLink = true;
}
else // I have not seen the source of the notification
{
ClassTxt = "MSG_TIT_NEW";
ClassLink = "LT BT_LINK MSG_TIT_NEW";
ClassAuthor = "MSG_AUT_NEW";
ClassBg = "MSG_BG_NEW";
PutLink = true;
}
2014-12-01 23:55:08 +01:00
/***** Write row for this notification *****/
/* Write event icon */
HTM_TR_Begin (NULL);
HTM_TD_Begin ("class=\"LT %s_%s\" style=\"width:25px;\"",
ClassBg,The_GetSuffix ());
if (PutLink)
{
Action = Ntf_StartFormGoToAction (NotifyEvent,Hie.Crs.CrsCod,&UsrDat,Cod,&Forums);
PutLink = Frm_CheckIfInside ();
}
if (PutLink)
{
Ico_PutIconLink (Ntf_Icons[NotifyEvent],Ico_BLACK,Action);
Frm_EndForm ();
}
else
Ico_PutIconOff (Ntf_Icons[NotifyEvent],Ico_BLACK,
Txt_NOTIFY_EVENTS_SINGULAR[NotifyEvent]);
HTM_TD_End ();
/* Write event type */
HTM_TD_Begin ("class=\"LT %s_%s\"",ClassBg,The_GetSuffix ());
if (PutLink)
{
Action = Ntf_StartFormGoToAction (NotifyEvent,Hie.Crs.CrsCod,&UsrDat,Cod,&Forums);
PutLink = Frm_CheckIfInside ();
HTM_BUTTON_Submit_Begin (Txt_NOTIFY_EVENTS_SINGULAR[NotifyEvent],
"class=\"LT %s_%s\"",
ClassLink,The_GetSuffix ());
HTM_Txt (Txt_NOTIFY_EVENTS_SINGULAR[NotifyEvent]);
HTM_BUTTON_End ();
Frm_EndForm ();
}
else
{
HTM_SPAN_Begin ("class=\"%s\"",ClassTxt);
HTM_Txt (Txt_NOTIFY_EVENTS_SINGULAR[NotifyEvent]);
HTM_SPAN_End ();
}
HTM_TD_End ();
/* Write user (from) */
HTM_TD_Begin ("class=\"LT %s_%s %s_%s\"",
ClassAuthor,The_GetSuffix (),
ClassBg,The_GetSuffix ());
Usr_WriteAuthor (&UsrDat,Cns_ENABLED);
HTM_TD_End ();
/* Write location */
HTM_TD_Begin ("class=\"LT %s_%s\"",
ClassBg,The_GetSuffix ());
if (NotifyEvent == Ntf_EVENT_FORUM_POST_COURSE ||
NotifyEvent == Ntf_EVENT_FORUM_REPLY)
{
if (PutLink)
{
Action = Ntf_StartFormGoToAction (NotifyEvent,Hie.Crs.CrsCod,&UsrDat,Cod,&Forums);
PutLink = Frm_CheckIfInside ();
}
if (PutLink)
HTM_BUTTON_Submit_Begin (Txt_NOTIFY_EVENTS_SINGULAR[NotifyEvent],
"class=\"LT %s_%s\"",
ClassLink,The_GetSuffix ());
else
HTM_SPAN_Begin ("class=\"%s_%s\"",
ClassTxt,The_GetSuffix ());
HTM_TxtF ("%s:&nbsp;%s",Txt_Forum,ForumName);
if (PutLink)
{
HTM_BUTTON_End ();
Frm_EndForm ();
}
else
HTM_SPAN_End ();
}
else
{
if (PutLink)
{
Action = Ntf_StartFormGoToAction (NotifyEvent,Hie.Crs.CrsCod,&UsrDat,Cod,&Forums);
PutLink = Frm_CheckIfInside ();
}
if (PutLink)
HTM_BUTTON_Submit_Begin (Txt_NOTIFY_EVENTS_SINGULAR[NotifyEvent],
"class=\"LT %s_%s\"",
ClassLink,The_GetSuffix ());
else
HTM_SPAN_Begin ("class=\"%s_%s\"",
ClassTxt,The_GetSuffix ());
if (Hie.Crs.CrsCod > 0)
HTM_TxtF ("%s:&nbsp;%s",Txt_Course,Hie.Crs.ShrtName);
else if (Hie.Deg.DegCod > 0)
HTM_TxtF ("%s:&nbsp;%s",Txt_Degree,Hie.Deg.ShrtName);
else if (Hie.Ctr.CtrCod > 0)
HTM_TxtF ("%s:&nbsp;%s",Txt_Center,Hie.Ctr.ShrtName);
else if (Hie.Ins.InsCod > 0)
HTM_TxtF ("%s:&nbsp;%s",Txt_Institution,Hie.Ins.ShrtName);
else
HTM_Hyphen ();
if (PutLink)
{
HTM_BUTTON_End ();
Frm_EndForm ();
}
else
HTM_SPAN_End ();
}
HTM_TD_End ();
/* Write date and time */
Msg_WriteMsgDate (DateTimeUTC,ClassTxt,ClassBg);
/* Write status (sent by email / pending to be sent by email) */
HTM_TD_Begin ("class=\"LT %s_%s %s_%s\"",
ClassTxt,The_GetSuffix (),
ClassBg,The_GetSuffix ());
HTM_Txt (Txt_NOTIFICATION_STATUS[StatusTxt]);
HTM_TD_End ();
HTM_TR_End ();
/***** Write content of the event *****/
if (PutLink)
{
ContentStr = NULL;
2019-12-17 00:36:22 +01:00
Ntf_GetNotifSummaryAndContent (SummaryStr,&ContentStr,NotifyEvent,
Cod,Hie.Crs.CrsCod,Gbl.Usrs.Me.UsrDat.UsrCod,
false);
HTM_TR_Begin (NULL);
2019-10-07 17:36:41 +02:00
HTM_TD_Begin ("colspan=\"2\"");
HTM_TD_End ();
2019-10-07 17:36:41 +02:00
HTM_TD_Begin ("colspan=\"4\" class=\"LT DAT_%s\""
" style=\"padding-bottom:12px;\"",
The_GetSuffix ());
HTM_Txt (SummaryStr);
HTM_TD_End ();
2019-10-07 17:36:41 +02:00
HTM_TR_End ();
}
}
2014-12-01 23:55:08 +01:00
/***** End table *****/
HTM_TABLE_End ();
2014-12-01 23:55:08 +01:00
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
}
else
Ale_ShowAlert (Ale_INFO,AllNotifications ? Txt_You_have_no_notifications :
Txt_You_have_no_unread_notifications);
2016-11-26 17:40:48 +01:00
2017-06-12 14:16:33 +02:00
/***** End box *****/
2019-10-25 22:48:34 +02:00
Box_BoxEnd ();
2014-12-01 23:55:08 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
/***** Reset to 0 the number of new notifications *****/
Ntf_DB_UpdateMyLastAccessToNotifications ();
2014-12-01 23:55:08 +01:00
}
2016-11-07 14:24:44 +01:00
/*****************************************************************************/
/****************** Put contextual icons in notifications ********************/
/*****************************************************************************/
2020-04-08 03:41:05 +02:00
static void Ntf_PutIconsNotif (__attribute__((unused)) void *Args)
2016-11-07 14:24:44 +01:00
{
2020-04-08 03:41:05 +02:00
/***** Put icon to show a figure *****/
Fig_PutIconToShowFigure (Fig_NOTIFY_EVENTS);
2016-11-07 14:24:44 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/********** Write a form to select whether show all notifications ************/
/*****************************************************************************/
static void Ntf_WriteFormAllNotifications (bool AllNotifications)
{
extern const char *Txt_Show_all_notifications;
2016-11-22 10:19:10 +01:00
extern const char *Txt_Show_all_NOTIFICATIONS;
2014-12-01 23:55:08 +01:00
2020-04-10 19:14:08 +02:00
Lay_PutContextualCheckbox (ActSeeNtf,
NULL,
2017-05-22 12:23:08 +02:00
"All",
AllNotifications,false,
2016-11-22 10:44:58 +01:00
Txt_Show_all_notifications,
Txt_Show_all_NOTIFICATIONS);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************* Get whether to show all notifications from form ***************/
/*****************************************************************************/
static bool Ntf_GetAllNotificationsFromForm (void)
{
return Par_GetParBool ("All");
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2015-12-29 13:18:25 +01:00
/*********** Put form to go to an action depending on the event **************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
static Act_Action_t Ntf_StartFormGoToAction (Ntf_NotifyEvent_t NotifyEvent,
long CrsCod,struct Usr_Data *UsrDat,long Cod,
const struct For_Forums *Forums)
2014-12-01 23:55:08 +01:00
{
extern const Act_Action_t For_ActionsSeeFor[For_NUM_TYPES_FORUM];
struct Brw_FileMetadata FileMetadata;
2016-01-02 17:07:58 +01:00
long InsCod = -1L;
long CtrCod = -1L;
long DegCod = -1L;
2014-12-01 23:55:08 +01:00
long GrpCod = -1L;
Act_Action_t Action = ActUnk;
2022-09-18 16:32:59 +02:00
char *Anchor = NULL;
2014-12-01 23:55:08 +01:00
/***** Parameters depending on the type of event *****/
switch (NotifyEvent)
{
2022-09-18 16:32:59 +02:00
case Ntf_EVENT_CALL_FOR_EXAM:
/* Build anchor string */
Frm_SetAnchorStr (Cod,&Anchor);
/* Begin form */
Action = ActSeeOneCfe;
Frm_BeginFormAnchor (ActSeeOneCfe,Anchor);
ParCod_PutPar (ParCod_Exa,Cod);
2022-09-18 16:32:59 +02:00
/* Free anchor string */
Frm_FreeAnchorStr (&Anchor);
2022-09-18 16:32:59 +02:00
break;
2014-12-01 23:55:08 +01:00
case Ntf_EVENT_DOCUMENT_FILE:
2016-04-22 09:47:25 +02:00
case Ntf_EVENT_TEACHERS_FILE:
2014-12-01 23:55:08 +01:00
case Ntf_EVENT_SHARED_FILE:
case Ntf_EVENT_MARKS_FILE:
2016-01-03 01:13:57 +01:00
FileMetadata.FilCod = Cod;
if (FileMetadata.FilCod > 0)
2014-12-01 23:55:08 +01:00
Brw_GetFileMetadataByCod (&FileMetadata);
2016-01-03 15:36:46 +01:00
if (FileMetadata.FilCod > 0)
2016-01-03 01:13:57 +01:00
{
2016-01-03 15:36:46 +01:00
Brw_GetCrsGrpFromFileMetadata (FileMetadata.FileBrowser,FileMetadata.Cod,
&InsCod,&CtrCod,&DegCod,&CrsCod,&GrpCod);
switch (NotifyEvent)
{
case Ntf_EVENT_DOCUMENT_FILE:
Action = (GrpCod > 0 ? ActReqDatSeeDocGrp :
(CrsCod > 0 ? ActReqDatSeeDocCrs :
(DegCod > 0 ? ActReqDatSeeDocDeg :
(CtrCod > 0 ? ActReqDatSeeDocCtr :
ActReqDatSeeDocIns))));
break;
2016-04-22 09:47:25 +02:00
case Ntf_EVENT_TEACHERS_FILE:
Action = (GrpCod > 0 ? ActReqDatTchGrp :
ActReqDatTchCrs);
break;
2016-01-03 15:36:46 +01:00
case Ntf_EVENT_SHARED_FILE:
Action = (GrpCod > 0 ? ActReqDatShaGrp :
(CrsCod > 0 ? ActReqDatShaCrs :
(DegCod > 0 ? ActReqDatShaDeg :
(CtrCod > 0 ? ActReqDatShaCtr :
ActReqDatShaIns))));
break;
case Ntf_EVENT_MARKS_FILE:
Action = (GrpCod > 0 ? ActReqDatSeeMrkGrp :
ActReqDatSeeMrkCrs);
break;
default: // Not aplicable here
break;
}
Frm_BeginForm (Action);
ParCod_PutPar (ParCod_Grp,GrpCod);
ParCod_PutPar (ParCod_Fil,FileMetadata.FilCod);
2016-01-03 01:13:57 +01:00
}
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_TML_COMMENT:
case Ntf_EVENT_TML_FAV:
case Ntf_EVENT_TML_SHARE:
case Ntf_EVENT_TML_MENTION:
2016-01-23 01:38:55 +01:00
// Cod is the code of the social publishing
Action = ActSeeGblTL;
Frm_BeginForm (Action);
ParCod_PutPar (ParCod_Pub,Cod);
Usr_PutParUsrCodEncrypted (UsrDat->EnUsrCod);
Ntf_PutParNotifyEvent (NotifyEvent);
2016-01-22 12:42:43 +01:00
break;
2016-01-23 19:11:07 +01:00
case Ntf_EVENT_FOLLOWER:
if (UsrDat->EnUsrCod[0]) // User's code found ==>
2016-01-20 21:18:38 +01:00
// go to user's public profile
{
Action = ActSeeOthPubPrf;
Frm_BeginForm (Action);
/* Put param to go to follower's profile */
Usr_PutParUsrCodEncrypted (UsrDat->EnUsrCod);
2016-01-20 21:18:38 +01:00
}
else // No user's code found ==> go to see my followers
{
Action = ActSeeFlr;
Frm_BeginForm (Action);
}
2015-12-29 13:18:25 +01:00
break;
2014-12-01 23:55:08 +01:00
case Ntf_EVENT_FORUM_POST_COURSE:
case Ntf_EVENT_FORUM_REPLY:
Action = For_ActionsSeeFor[Forums->Forum.Type];
Frm_BeginForm (Action);
For_PutAllParsForum (1, // Page of threads = first
1, // Page of posts = first
Forums->ForumSet,
Forums->ThreadsOrder,
Forums->Forum.HieCod,
Forums->Thread.Selected,
-1L);
2014-12-01 23:55:08 +01:00
break;
2016-01-20 21:18:38 +01:00
case Ntf_EVENT_NOTICE:
Action = ActSeeOneNot;
Frm_BeginForm (Action);
ParCod_PutPar (ParCod_Not,Cod);
2016-01-20 21:18:38 +01:00
break;
2014-12-01 23:55:08 +01:00
case Ntf_EVENT_MESSAGE:
Action = ActExpRcvMsg;
Frm_BeginForm (Action);
ParCod_PutPar (ParCod_Msg,Cod);
2014-12-01 23:55:08 +01:00
break;
default:
Action = Ntf_DefaultActions[NotifyEvent];
Frm_BeginForm (Action);
2014-12-01 23:55:08 +01:00
break;
}
/***** Parameter to go to another course/degree/center/institution *****/
if (Frm_CheckIfInside ())
2016-01-02 17:07:58 +01:00
{
2017-10-24 11:26:01 +02:00
if (CrsCod > 0) // Course specified
2016-01-03 01:13:57 +01:00
{
2019-04-04 10:45:15 +02:00
if (CrsCod != Gbl.Hierarchy.Crs.CrsCod) // Not the current course
ParCod_PutPar (ParCod_Crs,CrsCod); // Go to another course
2016-01-03 01:13:57 +01:00
}
else if (DegCod > 0) // Degree specified
{
2019-04-03 20:57:04 +02:00
if (DegCod != Gbl.Hierarchy.Deg.DegCod) // Not the current degree
ParCod_PutPar (ParCod_Deg,DegCod); // Go to another degree
2016-01-03 01:13:57 +01:00
}
else if (CtrCod > 0) // Center specified
2016-01-03 01:13:57 +01:00
{
if (CtrCod != Gbl.Hierarchy.Ctr.CtrCod) // Not the current center
ParCod_PutPar (ParCod_Ctr,CtrCod); // Go to another center
2016-01-03 01:13:57 +01:00
}
else if (InsCod > 0) // Institution specified
{
2019-04-03 20:57:04 +02:00
if (InsCod != Gbl.Hierarchy.Ins.InsCod) // Not the current institution
ParCod_PutPar (ParCod_Ins,InsCod); // Go to another institution
2016-01-03 01:13:57 +01:00
}
2016-01-02 17:07:58 +01:00
}
2016-01-03 01:13:57 +01:00
return Action;
2014-12-01 23:55:08 +01:00
}
2016-01-25 14:40:57 +01:00
/*****************************************************************************/
/******************* Get parameter with notify event type ********************/
/*****************************************************************************/
static void Ntf_PutParNotifyEvent (Ntf_NotifyEvent_t NotifyEvent)
2016-01-25 14:40:57 +01:00
{
Par_PutParUnsigned (NULL,"NotifyEvent",(unsigned) NotifyEvent);
2016-01-25 14:40:57 +01:00
}
/*****************************************************************************/
/******************* Get parameter with notify event type ********************/
/*****************************************************************************/
Ntf_NotifyEvent_t Ntf_GetParNotifyEvent (void)
2016-01-25 14:40:57 +01:00
{
2017-01-29 21:41:08 +01:00
return (Ntf_NotifyEvent_t)
Par_GetParUnsignedLong ("NotifyEvent",
0,
Ntf_NUM_NOTIFY_EVENTS - 1,
(unsigned long) Ntf_EVENT_UNKNOWN);
2016-01-25 14:40:57 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/****************** Set StatusTxt depending on status bits *******************/
/*****************************************************************************/
// Ntf_STATUS_NO_EMAIL = 0, // --0 !(Status & Ntf_STATUS_BIT_EMAIL)
// Ntf_STATUS_EMAIL_PENDING = 1, // 001 (Status & Ntf_STATUS_BIT_EMAIL) && !(Status & Ntf_STATUS_BIT_SENT) && !(Status & Ntf_STATUS_BIT_READ)
// Ntf_STATUS_EMAIL_CANCELLED = 2, // 101 (Status & Ntf_STATUS_BIT_EMAIL) && !(Status & Ntf_STATUS_BIT_SENT) && (Status & Ntf_STATUS_BIT_READ)
// Ntf_STATUS_EMAIL_SENT = 3, // -11 (Status & Ntf_STATUS_BIT_EMAIL) && (Status & Ntf_STATUS_BIT_SENT)
Ntf_StatusTxt_t Ntf_GetStatusTxtFromStatusBits (Ntf_Status_t Status)
{
if (!(Status & Ntf_STATUS_BIT_EMAIL))
return Ntf_STATUS_NO_EMAIL;
if ( (Status & Ntf_STATUS_BIT_SENT))
return Ntf_STATUS_EMAIL_SENT;
if ( (Status & (Ntf_STATUS_BIT_READ | Ntf_STATUS_BIT_REMOVED)))
return Ntf_STATUS_EMAIL_CANCELLED;
return Ntf_STATUS_EMAIL_PENDING;
}
/*****************************************************************************/
2015-12-28 19:22:56 +01:00
/******************* Get notification summary and content ********************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2017-03-08 14:12:33 +01:00
void Ntf_GetNotifSummaryAndContent (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1],
2017-01-13 10:49:56 +01:00
char **ContentStr,
2016-01-22 12:05:25 +01:00
Ntf_NotifyEvent_t NotifyEvent,
long Cod,long CrsCod,long UsrCod,
2017-03-06 13:01:16 +01:00
bool GetContent)
2014-12-01 23:55:08 +01:00
{
SummaryStr[0] = '\0';
switch (NotifyEvent)
{
case Ntf_EVENT_UNKNOWN:
break;
case Ntf_EVENT_DOCUMENT_FILE:
2016-04-22 09:47:25 +02:00
case Ntf_EVENT_TEACHERS_FILE:
2014-12-01 23:55:08 +01:00
case Ntf_EVENT_SHARED_FILE:
2017-03-06 13:01:16 +01:00
Brw_GetSummaryAndContentOfFile (SummaryStr,ContentStr,Cod,GetContent);
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_ASSIGNMENT:
2017-03-06 13:01:16 +01:00
Asg_GetNotifAssignment (SummaryStr,ContentStr,Cod,GetContent);
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_CALL_FOR_EXAM:
Cfe_GetSummaryAndContentCallForExam (SummaryStr,ContentStr,Cod,GetContent);
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_MARKS_FILE:
2017-03-06 13:01:16 +01:00
Mrk_GetNotifMyMarks (SummaryStr,ContentStr,Cod,UsrCod,GetContent);
2014-12-01 23:55:08 +01:00
break;
2017-05-21 18:08:35 +02:00
case Ntf_EVENT_ENROLMENT_STD:
2017-06-04 18:18:54 +02:00
case Ntf_EVENT_ENROLMENT_NET:
2017-05-21 18:08:35 +02:00
case Ntf_EVENT_ENROLMENT_TCH:
2017-03-30 11:20:06 +02:00
Enr_GetNotifEnrolment (SummaryStr,CrsCod,UsrCod);
2014-12-01 23:55:08 +01:00
break;
2017-03-30 11:20:06 +02:00
case Ntf_EVENT_ENROLMENT_REQUEST:
Enr_GetNotifEnrolmentRequest (SummaryStr,ContentStr,Cod,GetContent);
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_TML_COMMENT:
case Ntf_EVENT_TML_FAV:
case Ntf_EVENT_TML_SHARE:
case Ntf_EVENT_TML_MENTION:
2016-01-23 01:38:55 +01:00
// Cod is the code of the social publishing
TmlNtf_GetNotifPublication (SummaryStr,ContentStr,Cod,GetContent);
2016-01-22 01:47:28 +01:00
break;
2016-01-23 19:11:07 +01:00
case Ntf_EVENT_FOLLOWER:
2016-01-22 01:47:28 +01:00
Fol_GetNotifFollower (SummaryStr,ContentStr);
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_FORUM_POST_COURSE:
case Ntf_EVENT_FORUM_REPLY:
2017-03-06 13:01:16 +01:00
For_GetSummaryAndContentForumPst (SummaryStr,ContentStr,Cod,GetContent);
2014-12-01 23:55:08 +01:00
break;
2016-01-22 01:47:28 +01:00
case Ntf_EVENT_NOTICE:
2017-03-06 13:01:16 +01:00
Not_GetSummaryAndContentNotice (SummaryStr,ContentStr,Cod,GetContent);
2016-01-22 01:47:28 +01:00
break;
2014-12-01 23:55:08 +01:00
case Ntf_EVENT_MESSAGE:
2017-03-06 13:01:16 +01:00
Msg_GetNotifMessage (SummaryStr,ContentStr,Cod,GetContent);
2014-12-01 23:55:08 +01:00
if (Gbl.WebService.IsWebService)
/* Set the message as open by me, because I can read it in an extern application */
Msg_DB_SetRcvMsgAsOpen (Cod,UsrCod);
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_SURVEY:
2017-03-06 13:01:16 +01:00
Svy_GetNotifSurvey (SummaryStr,ContentStr,Cod,GetContent);
2014-12-01 23:55:08 +01:00
break;
}
}
/*****************************************************************************/
2016-01-04 01:56:28 +01:00
/*********** Mark possible notifications of one file as removed **************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-01-04 01:56:28 +01:00
void Ntf_MarkNotifOneFileAsRemoved (const char *Path)
2014-12-01 23:55:08 +01:00
{
extern const Brw_FileBrowser_t Brw_DB_FileBrowserForDB_files[Brw_NUM_TYPES_FILE_BROWSER];
static const Ntf_NotifyEvent_t NotifyEvent[Brw_NUM_TYPES_FILE_BROWSER] =
{
[Brw_ADMI_DOC_CRS] = Ntf_EVENT_DOCUMENT_FILE,
[Brw_ADMI_DOC_GRP] = Ntf_EVENT_DOCUMENT_FILE,
[Brw_ADMI_TCH_CRS] = Ntf_EVENT_TEACHERS_FILE,
[Brw_ADMI_TCH_GRP] = Ntf_EVENT_TEACHERS_FILE,
[Brw_ADMI_SHR_CRS] = Ntf_EVENT_SHARED_FILE,
[Brw_ADMI_SHR_GRP] = Ntf_EVENT_SHARED_FILE,
[Brw_ADMI_MRK_CRS] = Ntf_EVENT_MARKS_FILE,
[Brw_ADMI_MRK_GRP] = Ntf_EVENT_MARKS_FILE,
};
Brw_FileBrowser_t FileBrowser = Brw_DB_FileBrowserForDB_files[Gbl.FileBrowser.Type];
2016-01-04 01:02:07 +01:00
long FilCod;
2014-12-01 23:55:08 +01:00
if (NotifyEvent[FileBrowser])
2014-12-01 23:55:08 +01:00
{
/***** Get file code *****/
FilCod = Brw_DB_GetFilCodByPath (Path,false); // Any file, public or not
if (FilCod > 0)
/***** Set notification as removed *****/
Ntf_DB_MarkNotifAsRemoved (NotifyEvent[FileBrowser],FilCod);
2014-12-01 23:55:08 +01:00
}
2016-01-04 01:02:07 +01:00
}
/*****************************************************************************/
2016-01-04 01:56:28 +01:00
/*** Mark possible notifications involving children of a folder as removed ***/
2016-01-04 01:02:07 +01:00
/*****************************************************************************/
2016-01-04 01:56:28 +01:00
void Ntf_MarkNotifChildrenOfFolderAsRemoved (const char *Path)
2016-01-04 01:02:07 +01:00
{
extern const Brw_FileBrowser_t Brw_DB_FileBrowserForDB_files[Brw_NUM_TYPES_FILE_BROWSER];
static const Ntf_NotifyEvent_t NotifyEvent[Brw_NUM_TYPES_FILE_BROWSER] =
{
[Brw_ADMI_DOC_CRS] = Ntf_EVENT_DOCUMENT_FILE,
[Brw_ADMI_DOC_GRP] = Ntf_EVENT_DOCUMENT_FILE,
[Brw_ADMI_TCH_CRS] = Ntf_EVENT_TEACHERS_FILE,
[Brw_ADMI_TCH_GRP] = Ntf_EVENT_TEACHERS_FILE,
[Brw_ADMI_SHR_CRS] = Ntf_EVENT_SHARED_FILE,
[Brw_ADMI_SHR_GRP] = Ntf_EVENT_SHARED_FILE,
[Brw_ADMI_MRK_CRS] = Ntf_EVENT_MARKS_FILE,
[Brw_ADMI_MRK_GRP] = Ntf_EVENT_MARKS_FILE,
};
Brw_FileBrowser_t FileBrowser = Brw_DB_FileBrowserForDB_files[Gbl.FileBrowser.Type];
2014-12-01 23:55:08 +01:00
if (NotifyEvent[FileBrowser])
/***** Set notification as removed *****/
Ntf_DB_MarkNotifChildrenOfFolderAsRemoved (NotifyEvent[FileBrowser],FileBrowser,
Brw_GetCodForFileBrowser (),
Path);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2016-01-22 12:42:43 +01:00
/********** Get a list with user's codes of all users to be notified *********/
/********** about an event, and notify them *********/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-11-16 23:19:52 +01:00
// Return the number of users notified by email
2014-12-01 23:55:08 +01:00
unsigned Ntf_StoreNotifyEventsToAllUsrs (Ntf_NotifyEvent_t NotifyEvent,long Cod)
{
static unsigned (*GetUsrsBrowser[Brw_NUM_TYPES_FILE_BROWSER]) (MYSQL_RES **mysql_res) =
{
// Notify all users in course except me
[Brw_ADMI_DOC_CRS] = Enr_DB_GetUsrsFromCurrentCrsExceptMe,
[Brw_ADMI_SHR_CRS] = Enr_DB_GetUsrsFromCurrentCrsExceptMe,
[Brw_ADMI_MRK_CRS] = Enr_DB_GetUsrsFromCurrentCrsExceptMe,
// Notify all teachers in course except me
[Brw_ADMI_TCH_CRS] = Enr_DB_GetTchsFromCurrentCrsExceptMe,
// Notify all users in group except me
[Brw_ADMI_DOC_GRP] = Grp_DB_GetUsrsFromCurrentGrpExceptMe,
[Brw_ADMI_SHR_GRP] = Grp_DB_GetUsrsFromCurrentGrpExceptMe,
[Brw_ADMI_MRK_GRP] = Grp_DB_GetUsrsFromCurrentGrpExceptMe,
// Notify all teachers in group except me
[Brw_ADMI_TCH_GRP] = Grp_DB_GetTchsFromCurrentGrpExceptMe,
};
static unsigned (*GetUsrsForum[For_NUM_TYPES_FORUM]) (MYSQL_RES **mysql_res) =
{
[For_FORUM_COURSE_USRS] = Enr_DB_GetUsrsFromCurrentCrsExceptMe,
[For_FORUM_COURSE_TCHS] = Enr_DB_GetTchsFromCurrentCrsExceptMe,
};
2014-12-01 23:55:08 +01:00
MYSQL_RES *mysql_res;
unsigned NumUsrs = 0; // Initialized to avoid warning
unsigned NumUsr;
struct Usr_Data UsrDat;
2020-04-07 03:01:41 +02:00
struct For_Forum ForumSelected;
long InsCod;
long CtrCod;
long DegCod;
long CrsCod;
2014-12-01 23:55:08 +01:00
unsigned NumUsrsToBeNotifiedByEMail = 0;
unsigned NotifyEventMask = (1 << NotifyEvent);
/***** Get users who want to be notified from database ******/
switch (NotifyEvent)
{
case Ntf_EVENT_UNKNOWN: // This function should not be called in this case
return 0;
case Ntf_EVENT_DOCUMENT_FILE:
2016-04-22 09:47:25 +02:00
case Ntf_EVENT_TEACHERS_FILE:
2014-12-01 23:55:08 +01:00
case Ntf_EVENT_SHARED_FILE:
case Ntf_EVENT_MARKS_FILE:
if (GetUsrsBrowser[Gbl.FileBrowser.Type])
NumUsrs = GetUsrsBrowser[Gbl.FileBrowser.Type] (&mysql_res);
else
return 0;
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_ASSIGNMENT:
NumUsrs = Asg_DB_GetUsrsFromAssignmentExceptMe (&mysql_res,Cod);
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_CALL_FOR_EXAM:
2014-12-01 23:55:08 +01:00
case Ntf_EVENT_NOTICE:
NumUsrs = Enr_DB_GetUsrsFromCurrentCrsExceptMe (&mysql_res);
2014-12-01 23:55:08 +01:00
break;
2017-05-21 18:08:35 +02:00
case Ntf_EVENT_ENROLMENT_STD: // This function should not be called in this case
2017-06-04 18:18:54 +02:00
case Ntf_EVENT_ENROLMENT_NET: // This function should not be called in this case
2017-05-21 18:08:35 +02:00
case Ntf_EVENT_ENROLMENT_TCH: // This function should not be called in this case
2014-12-01 23:55:08 +01:00
return 0;
2017-03-30 11:20:06 +02:00
case Ntf_EVENT_ENROLMENT_REQUEST:
if (Enr_GetNumUsrsInCrss (HieLvl_CRS,Gbl.Hierarchy.Crs.CrsCod,
2020-01-08 23:49:04 +01:00
1 << Rol_TCH))
2014-12-01 23:55:08 +01:00
// If this course has teachers ==> send notification to teachers
NumUsrs = Enr_DB_GetTchsFromCurrentCrsExceptMe (&mysql_res);
2014-12-01 23:55:08 +01:00
else // Course without teachers
// If this course has no teachers
// and I want to be a teacher (checked before calling this function
// to not send requests to be a student to admins)
// ==> send notification to administrators or superusers
NumUsrs = Adm_DB_GetAdmsCurrentScopeExceptMe (&mysql_res);
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_TML_COMMENT: // New comment to one of my social notes or comments
2016-01-23 01:38:55 +01:00
// Cod is the code of the social publishing
NumUsrs = Tml_DB_GetPublishersInNoteExceptMe (&mysql_res,Cod);
2016-01-22 01:47:28 +01:00
break;
case Ntf_EVENT_TML_FAV: // New favourite to one of my social notes or comments
case Ntf_EVENT_TML_SHARE: // New sharing of one of my social notes
case Ntf_EVENT_TML_MENTION:
2016-01-23 19:11:07 +01:00
case Ntf_EVENT_FOLLOWER:
2016-01-23 01:38:55 +01:00
// This function should not be called in these cases
2016-01-22 01:47:28 +01:00
return 0;
2014-12-01 23:55:08 +01:00
case Ntf_EVENT_FORUM_POST_COURSE:
// Check if forum is for users or for all users in the course
For_GetThreadForumTypeAndHieCodOfAPost (Cod,&ForumSelected);
if (GetUsrsForum[ForumSelected.Type])
NumUsrs = GetUsrsForum[ForumSelected.Type] (&mysql_res);
else
return 0;
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_FORUM_REPLY:
// Cod is the code of the post
NumUsrs = For_DB_GetPublishersInThreadExceptMe (&mysql_res,Cod);
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_MESSAGE: // This function should not be called in this case
return 0;
case Ntf_EVENT_SURVEY: // Only surveys for a course are notified, not surveys for a degree or global
NumUsrs = Svy_DB_GetUsrsFromSurveyExceptMe (&mysql_res,Cod);
2014-12-01 23:55:08 +01:00
break;
}
2020-04-07 03:01:41 +02:00
if (NotifyEvent == Ntf_EVENT_FORUM_POST_COURSE ||
NotifyEvent == Ntf_EVENT_FORUM_REPLY)
{
InsCod = CtrCod = DegCod = CrsCod = -1L;
switch (ForumSelected.Type)
{
case For_FORUM_INSTIT_USRS:
case For_FORUM_INSTIT_TCHS:
InsCod = ForumSelected.HieCod;
2020-04-07 03:01:41 +02:00
break;
case For_FORUM_CENTER_USRS:
case For_FORUM_CENTER_TCHS:
CtrCod = ForumSelected.HieCod;
2020-04-07 03:01:41 +02:00
break;
case For_FORUM_DEGREE_USRS:
case For_FORUM_DEGREE_TCHS:
DegCod = ForumSelected.HieCod;
2020-04-07 03:01:41 +02:00
break;
case For_FORUM_COURSE_USRS:
case For_FORUM_COURSE_TCHS:
CrsCod = ForumSelected.HieCod;
2020-04-07 03:01:41 +02:00
break;
default:
break;
}
}
else
{
InsCod = Gbl.Hierarchy.Ins.InsCod;
CtrCod = Gbl.Hierarchy.Ctr.CtrCod;
DegCod = Gbl.Hierarchy.Deg.DegCod;
CrsCod = Gbl.Hierarchy.Crs.CrsCod;
}
if (NumUsrs) // Users found
2014-12-01 23:55:08 +01:00
{
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
/***** Notify the users one by one *****/
for (NumUsr = 0;
NumUsr < NumUsrs;
NumUsr++)
2014-12-01 23:55:08 +01:00
{
/* Get next user */
UsrDat.UsrCod = DB_GetNextCode (mysql_res);
2014-12-01 23:55:08 +01:00
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat, // Get user's data from database
Usr_DONT_GET_PREFS,
Usr_DONT_GET_ROLE_IN_CURRENT_CRS))
2019-03-19 13:22:14 +01:00
if ((UsrDat.NtfEvents.CreateNotif & NotifyEventMask)) // Create notification
2014-12-01 23:55:08 +01:00
{
2019-03-19 13:22:14 +01:00
if ((UsrDat.NtfEvents.SendEmail & NotifyEventMask)) // Send notification by email
2014-12-01 23:55:08 +01:00
{
Ntf_DB_StoreNotifyEventToUsr (NotifyEvent,UsrDat.UsrCod,Cod,
(Ntf_Status_t) Ntf_STATUS_BIT_EMAIL,
InsCod,CtrCod,DegCod,CrsCod);
2014-12-01 23:55:08 +01:00
NumUsrsToBeNotifiedByEMail++;
}
else // Don't send notification by email
Ntf_DB_StoreNotifyEventToUsr (NotifyEvent,UsrDat.UsrCod,Cod,
(Ntf_Status_t) 0,
InsCod,CtrCod,DegCod,CrsCod);
2014-12-01 23:55:08 +01:00
}
}
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return NumUsrsToBeNotifiedByEMail;
}
/*****************************************************************************/
2016-11-16 23:19:52 +01:00
/***************** Send all pending notifications by email *******************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Ntf_SendPendingNotifByEMailToAllUsrs (void)
{
MYSQL_RES *mysql_res;
unsigned NumUsrs;
unsigned NumUsr;
struct Usr_Data ToUsrDat;
2014-12-01 23:55:08 +01:00
unsigned NumNotif;
unsigned NumTotalNotif = 0;
unsigned NumMails;
unsigned NumTotalMails = 0;
/***** Get users who must be notified from database ******/
if ((NumUsrs = Ntf_DB_GetUsrsWhoMustBeNotified (&mysql_res)))
2014-12-01 23:55:08 +01:00
{
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&ToUsrDat);
2014-12-01 23:55:08 +01:00
/***** Notify the users one by one *****/
for (NumUsr = 0;
NumUsr < NumUsrs;
NumUsr++)
2014-12-01 23:55:08 +01:00
{
/* Get next user */
ToUsrDat.UsrCod = DB_GetNextCode (mysql_res);
2014-12-01 23:55:08 +01:00
/* Get user's data */
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&ToUsrDat, // Get user's data from database
Usr_GET_PREFS, // User's language necessary to write email
Usr_DONT_GET_ROLE_IN_CURRENT_CRS))
2014-12-01 23:55:08 +01:00
{
/* Send one email to this user */
Ntf_SendPendingNotifByEMailToOneUsr (&ToUsrDat,&NumNotif,&NumMails);
2014-12-01 23:55:08 +01:00
NumTotalNotif += NumNotif;
NumTotalMails += NumMails;
}
}
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&ToUsrDat);
2014-12-01 23:55:08 +01:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
/***** Delete old notifications ******/
Ntf_DB_RemoveOldNtfs ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2016-11-16 23:19:52 +01:00
/************ Send pending notifications of one user by email ****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
static void Ntf_SendPendingNotifByEMailToOneUsr (const struct Usr_Data *ToUsrDat,
unsigned *NumNotif,
unsigned *NumMails)
2014-12-01 23:55:08 +01:00
{
2018-12-08 16:43:13 +01:00
extern const char *Txt_NOTIFY_EVENTS_There_is_a_new_event_NO_HTML[1 + Lan_NUM_LANGUAGES];
extern const char *Txt_NOTIFY_EVENTS_There_are_X_new_events_NO_HTML[1 + Lan_NUM_LANGUAGES];
extern const char *Txt_NOTIFY_EVENTS_SINGULAR_NO_HTML[Ntf_NUM_NOTIFY_EVENTS][1 + Lan_NUM_LANGUAGES];
extern const char *Txt_Course_NO_HTML[1 + Lan_NUM_LANGUAGES];
extern const char *Txt_Forum_NO_HTML[1 + Lan_NUM_LANGUAGES];
extern const char *Txt_MSG_From_NO_HTML[1 + Lan_NUM_LANGUAGES];
extern const char *Txt_Go_to_NO_HTML[1 + Lan_NUM_LANGUAGES];
extern const char *Txt_TAB_Messages_NO_HTML[1 + Lan_NUM_LANGUAGES];
extern const char *Txt_Notifications_NO_HTML[1 + Lan_NUM_LANGUAGES];
extern const char *Txt_If_you_no_longer_wish_to_receive_email_notifications_NO_HTML[1 + Lan_NUM_LANGUAGES];
2014-12-01 23:55:08 +01:00
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumNtfs;
unsigned NumNtf;
2018-12-08 16:43:13 +01:00
Lan_Language_t ToUsrLanguage;
struct Usr_Data FromUsrDat;
2014-12-01 23:55:08 +01:00
Ntf_NotifyEvent_t NotifyEvent = (Ntf_NotifyEvent_t) 0; // Initialized to avoid warning
2021-02-11 23:27:48 +01:00
struct Hie_Hierarchy Hie;
2014-12-01 23:55:08 +01:00
long Cod;
2020-04-07 03:01:41 +02:00
struct For_Forum ForumSelected;
2017-01-13 10:49:56 +01:00
char ForumName[For_MAX_BYTES_FORUM_NAME + 1];
2020-04-11 15:21:30 +02:00
char FileNameMail[PATH_MAX + 1];
FILE *FileMail;
2014-12-01 23:55:08 +01:00
int ReturnCode;
/***** Return 0 notifications and 0 mails when error *****/
*NumNotif =
*NumMails = 0;
2014-12-01 23:55:08 +01:00
2016-10-12 14:02:56 +02:00
if (Mai_CheckIfUsrCanReceiveEmailNotif (ToUsrDat))
2014-12-01 23:55:08 +01:00
{
/***** Get pending notifications of this user from database ******/
if ((NumNtfs = Ntf_DB_GetPendingNtfsToUsr (&mysql_res,ToUsrDat->UsrCod))) // Notifications found
2014-12-01 23:55:08 +01:00
{
2015-12-07 23:13:08 +01:00
/***** If user has no language, set it to current language *****/
ToUsrLanguage = ToUsrDat->Prefs.Language;
2018-12-08 16:43:13 +01:00
if (ToUsrLanguage == Lan_LANGUAGE_UNKNOWN)
ToUsrLanguage = Cfg_DEFAULT_LANGUAGE;
2015-12-07 23:13:08 +01:00
2014-12-01 23:55:08 +01:00
/***** Create temporary file for mail content *****/
2020-04-11 15:21:30 +02:00
Mai_CreateFileNameMail (FileNameMail,&FileMail);
2014-12-01 23:55:08 +01:00
/***** Welcome note *****/
Mai_WriteWelcomeNoteEMail (FileMail,ToUsrDat,ToUsrLanguage);
if (NumNtfs == 1)
2020-04-11 15:21:30 +02:00
fprintf (FileMail,Txt_NOTIFY_EVENTS_There_is_a_new_event_NO_HTML[ToUsrLanguage],
2014-12-01 23:55:08 +01:00
Cfg_PLATFORM_SHORT_NAME);
else
2020-04-11 15:21:30 +02:00
fprintf (FileMail,Txt_NOTIFY_EVENTS_There_are_X_new_events_NO_HTML[ToUsrLanguage],
(unsigned) NumNtfs,Cfg_PLATFORM_SHORT_NAME);
2020-04-11 15:21:30 +02:00
fprintf (FileMail,": \n");
2014-12-01 23:55:08 +01:00
/***** Initialize structure with origin user's data *****/
Usr_UsrDataConstructor (&FromUsrDat);
/***** Inform about the events one by one *****/
for (NumNtf = 0;
NumNtf < NumNtfs;
NumNtf++)
2014-12-01 23:55:08 +01:00
{
/* Get next event */
row = mysql_fetch_row (mysql_res);
/*
row[0]: NotifyEvent
row[1]: FromUsrCod
row[2]: InsCod
row[3]: CtrCod
row[4]: DegCod
row[5]: CrsCod
row[6]: Cod
*/
2014-12-01 23:55:08 +01:00
/* Get event type (row[0]) */
NotifyEvent = Ntf_GetNotifyEventFromStr (row[0]);
2014-12-01 23:55:08 +01:00
/* Get origin user code (row[1]) */
FromUsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[1]);
Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&FromUsrDat, // Get origin user's data from database
Usr_DONT_GET_PREFS,
Usr_DONT_GET_ROLE_IN_CURRENT_CRS);
2014-12-01 23:55:08 +01:00
/* Get insti. code (row[2]),
center code (row[3]),
degree code (row[4]),
course code (row[5]) */
2021-02-11 23:27:48 +01:00
Hie.Ins.InsCod = Str_ConvertStrCodToLongCod (row[2]);
Hie.Ctr.CtrCod = Str_ConvertStrCodToLongCod (row[3]);
Hie.Deg.DegCod = Str_ConvertStrCodToLongCod (row[4]);
Hie.Crs.CrsCod = Str_ConvertStrCodToLongCod (row[5]);
/* Get data of institution, center, degree and course */
Ins_GetInstitDataByCod (&Hie.Ins);
Ctr_GetCenterDataByCod (&Hie.Ctr);
Deg_GetDegreeDataByCod (&Hie.Deg);
Crs_GetCourseDataByCod (&Hie.Crs);
2014-12-01 23:55:08 +01:00
/* Get message/post/... code (row[6]) */
Cod = Str_ConvertStrCodToLongCod (row[6]);
/* Get forum type */
if (NotifyEvent == Ntf_EVENT_FORUM_POST_COURSE ||
2016-10-12 14:02:56 +02:00
NotifyEvent == Ntf_EVENT_FORUM_REPLY)
For_GetThreadForumTypeAndHieCodOfAPost (Cod,&ForumSelected);
2014-12-01 23:55:08 +01:00
/* Information about the type of this event */
2020-04-11 15:21:30 +02:00
fprintf (FileMail,Txt_NOTIFY_EVENTS_SINGULAR_NO_HTML[NotifyEvent][ToUsrLanguage],
2014-12-01 23:55:08 +01:00
Cfg_PLATFORM_SHORT_NAME);
2020-04-11 15:21:30 +02:00
fprintf (FileMail,"\n");
2014-12-01 23:55:08 +01:00
/* Course/forum: */
switch (NotifyEvent)
{
case Ntf_EVENT_UNKNOWN:
case Ntf_EVENT_TML_COMMENT:
case Ntf_EVENT_TML_FAV:
case Ntf_EVENT_TML_SHARE:
case Ntf_EVENT_TML_MENTION:
2016-01-23 19:11:07 +01:00
case Ntf_EVENT_FOLLOWER:
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_DOCUMENT_FILE:
2016-04-22 09:47:25 +02:00
case Ntf_EVENT_TEACHERS_FILE:
2014-12-01 23:55:08 +01:00
case Ntf_EVENT_SHARED_FILE:
case Ntf_EVENT_ASSIGNMENT:
case Ntf_EVENT_CALL_FOR_EXAM:
2014-12-01 23:55:08 +01:00
case Ntf_EVENT_MARKS_FILE:
2017-05-21 18:08:35 +02:00
case Ntf_EVENT_ENROLMENT_STD:
2017-06-04 18:18:54 +02:00
case Ntf_EVENT_ENROLMENT_NET:
2017-05-21 18:08:35 +02:00
case Ntf_EVENT_ENROLMENT_TCH:
2017-03-30 11:20:06 +02:00
case Ntf_EVENT_ENROLMENT_REQUEST:
2014-12-01 23:55:08 +01:00
case Ntf_EVENT_NOTICE:
case Ntf_EVENT_MESSAGE:
case Ntf_EVENT_SURVEY:
2021-02-11 23:27:48 +01:00
if (Hie.Crs.CrsCod > 0)
2020-04-11 15:21:30 +02:00
fprintf (FileMail,"%s: %s\n",
2015-12-07 23:13:08 +01:00
Txt_Course_NO_HTML[ToUsrLanguage],
2021-02-11 23:27:48 +01:00
Hie.Crs.FullName);
2014-12-01 23:55:08 +01:00
break;
case Ntf_EVENT_FORUM_POST_COURSE:
case Ntf_EVENT_FORUM_REPLY:
2017-04-18 01:25:44 +02:00
For_SetForumName (&ForumSelected,
2015-12-07 23:13:08 +01:00
ForumName,ToUsrLanguage,false); // Set forum name in recipient's language
2020-04-11 15:21:30 +02:00
fprintf (FileMail,"%s: %s\n",
2015-12-07 23:13:08 +01:00
Txt_Forum_NO_HTML[ToUsrLanguage],
2014-12-01 23:55:08 +01:00
ForumName);
break;
}
/* From: */
2020-04-11 15:21:30 +02:00
fprintf (FileMail,"%s: %s\n",
2015-12-07 23:13:08 +01:00
Txt_MSG_From_NO_HTML[ToUsrLanguage],
2014-12-01 23:55:08 +01:00
FromUsrDat.FullName);
}
/***** Free memory used for origin user's data *****/
Usr_UsrDataDestructor (&FromUsrDat);
/* Go to: */
2020-04-11 15:21:30 +02:00
fprintf (FileMail,"%s: %s/ > %s > %s\n",
2015-12-07 23:13:08 +01:00
Txt_Go_to_NO_HTML[ToUsrLanguage],
2016-07-08 12:43:48 +02:00
Cfg_URL_SWAD_CGI,
2015-12-07 23:13:08 +01:00
Txt_TAB_Messages_NO_HTML[ToUsrLanguage],
Txt_Notifications_NO_HTML[ToUsrLanguage]);
2014-12-01 23:55:08 +01:00
/* Disclaimer */
2020-04-11 15:21:30 +02:00
fprintf (FileMail,"\n%s\n",
2015-12-07 23:13:08 +01:00
Txt_If_you_no_longer_wish_to_receive_email_notifications_NO_HTML[ToUsrLanguage]);
2014-12-01 23:55:08 +01:00
/* Footer note */
2020-04-11 15:21:30 +02:00
Mai_WriteFootNoteEMail (FileMail,ToUsrLanguage);
2014-12-01 23:55:08 +01:00
2020-04-11 15:21:30 +02:00
fclose (FileMail);
2014-12-01 23:55:08 +01:00
2016-11-16 23:19:52 +01:00
/***** Call the command to send an email *****/
ReturnCode = Mai_SendMailMsg (FileNameMail,
Txt_Notifications_NO_HTML[ToUsrLanguage],
ToUsrDat->Email);
2014-12-01 23:55:08 +01:00
/***** Remove temporary file *****/
2020-04-11 15:21:30 +02:00
unlink (FileNameMail);
2014-12-01 23:55:08 +01:00
/***** Update number of notifications, number of mails and statistics *****/
if (ReturnCode == 0) // Message sent successfully
{
*NumNotif = NumNtfs;
2014-12-01 23:55:08 +01:00
*NumMails = 1;
/* Update statistics about notifications */
Ntf_UpdateNumNotifSent (Hie.Deg.DegCod,Hie.Crs.CrsCod,NotifyEvent,
*NumNotif,*NumMails);
2014-12-01 23:55:08 +01:00
}
/***** Mark all pending notifications of this user as 'sent' *****/
Ntf_DB_MarkPendingNtfsAsSent (ToUsrDat->UsrCod);
2014-12-01 23:55:08 +01:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
}
/*****************************************************************************/
/****** Get notify event type from string number coming from database ********/
/*****************************************************************************/
2019-12-17 00:36:22 +01:00
Ntf_NotifyEvent_t Ntf_GetNotifyEventFromStr (const char *Str)
2014-12-01 23:55:08 +01:00
{
unsigned UnsignedNum;
if (sscanf (Str,"%u",&UnsignedNum) == 1)
if (UnsignedNum < Ntf_NUM_NOTIFY_EVENTS)
return (Ntf_NotifyEvent_t) UnsignedNum;
return Ntf_EVENT_UNKNOWN;
}
/*****************************************************************************/
2016-11-16 23:19:52 +01:00
/************* Get number of events notified and emails sent *****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
static void Ntf_GetNumNotifSent (long DegCod,long CrsCod,
Ntf_NotifyEvent_t NotifyEvent,
unsigned *NumEvents,unsigned *NumMails)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2016-11-16 23:19:52 +01:00
/***** Get number of notifications sent by email from database *****/
if (Ntf_DB_GetNumNotifSent (&mysql_res,DegCod,CrsCod,NotifyEvent))
2014-12-01 23:55:08 +01:00
{
row = mysql_fetch_row (mysql_res);
if (sscanf (row[0],"%u",NumEvents) != 1)
Err_ShowErrorAndExit ("Error when getting number of notifications sent by email.");
2014-12-01 23:55:08 +01:00
if (sscanf (row[1],"%u",NumMails) != 1)
Err_ShowErrorAndExit ("Error when getting number of notifications sent by email.");
2014-12-01 23:55:08 +01:00
}
else
*NumEvents = *NumMails = 0;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/********** Update number of notifications and notify emails sent ************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
static void Ntf_UpdateNumNotifSent (long DegCod,long CrsCod,
Ntf_NotifyEvent_t NotifyEvent,
unsigned NumEvents,unsigned NumMails)
{
unsigned CurrentNumEvents;
unsigned CurrentNumMails;
/***** Get number of events notified and number of mails sent *****/
Ntf_GetNumNotifSent (DegCod,CrsCod,NotifyEvent,&CurrentNumEvents,&CurrentNumMails);
/***** Update number of notifications and notify emails sent *****/
Ntf_DB_UpdateNumNotifSent (DegCod,CrsCod,NotifyEvent,
CurrentNumEvents + NumEvents,
CurrentNumMails + NumMails);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************** Mark all my notifications as seen **********************/
/*****************************************************************************/
void Ntf_MarkAllNotifAsSeen (void)
{
/***** Set all my notifications as seen *****/
Ntf_DB_MarkAllMyNotifAsSeen ();
2014-12-01 23:55:08 +01:00
/***** Show my notifications again *****/
Ntf_ShowMyNotifications ();
}
/*****************************************************************************/
2016-11-16 23:19:52 +01:00
/*** Activate the sending of email to notify me that I have new messages *****/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Ntf_PutFormChangeNotifSentByEMail (void)
{
2019-03-26 11:53:21 +01:00
extern const char *Hlp_PROFILE_Settings_notifications;
2015-01-01 19:39:46 +01:00
extern const char *Txt_Save_changes;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Notifications;
extern const char *Txt_Create_BR_notification;
2016-11-16 23:19:52 +01:00
extern const char *Txt_Notify_me_BR_by_email;
2014-12-01 23:55:08 +01:00
extern const char *Txt_NOTIFY_EVENTS_PLURAL[Ntf_NUM_NOTIFY_EVENTS];
Ntf_NotifyEvent_t NotifyEvent;
/***** Begin section with settings on privacy *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_Begin (Ntf_NOTIFICATIONS_ID);
2019-03-17 19:37:41 +01:00
/***** Begin box *****/
Box_BoxBegin (NULL,Txt_Notifications,
Ntf_PutIconsNotif,NULL,
Hlp_PROFILE_Settings_notifications,Box_NOT_CLOSABLE);
2015-04-11 23:46:21 +02:00
/***** Begin form *****/
Frm_BeginForm (ActChgNtfPrf);
2016-10-12 14:02:56 +02:00
/***** Warning if I can not receive email notifications *****/
if (!Mai_CheckIfUsrCanReceiveEmailNotif (&Gbl.Usrs.Me.UsrDat))
Mai_WriteWarningEmailNotifications ();
2019-10-12 00:07:52 +02:00
/***** List of notifications *****/
HTM_TABLE_BeginCenterPadding (2);
2019-10-12 00:07:52 +02:00
HTM_TR_Begin (NULL);
HTM_TH_Empty (1);
HTM_TH (Txt_Create_BR_notification,HTM_HEAD_CENTER);
HTM_TH (Txt_Notify_me_BR_by_email ,HTM_HEAD_CENTER);
HTM_TR_End ();
2019-10-12 00:07:52 +02:00
/***** Checkbox to activate internal notifications and email notifications
about events *****/
for (NotifyEvent = (Ntf_NotifyEvent_t) 1;
NotifyEvent <= (Ntf_NotifyEvent_t) (Ntf_NUM_NOTIFY_EVENTS - 1);
NotifyEvent++) // O is reserved for Ntf_EVENT_UNKNOWN
{
HTM_TR_Begin (NULL);
HTM_TD_Begin ("class=\"RM FORM_IN_%s\"",
The_GetSuffix ());
HTM_TxtColon (Txt_NOTIFY_EVENTS_PLURAL[NotifyEvent]);
HTM_TD_End ();
HTM_TD_Begin ("class=\"CM\"");
HTM_INPUT_CHECKBOX (Ntf_ParNotifMeAboutNotifyEvents[NotifyEvent],HTM_DONT_SUBMIT_ON_CHANGE,
"value=\"Y\"%s",
(Gbl.Usrs.Me.UsrDat.NtfEvents.CreateNotif &
(1 << NotifyEvent)) ? " checked=\"checked\"" :
"");
HTM_TD_End ();
HTM_TD_Begin ("class=\"CM\"");
HTM_INPUT_CHECKBOX (Ntf_ParEmailMeAboutNotifyEvents[NotifyEvent],HTM_DONT_SUBMIT_ON_CHANGE,
"value=\"Y\"%s",
(Gbl.Usrs.Me.UsrDat.NtfEvents.SendEmail &
(1 << NotifyEvent)) ? " checked=\"checked\"" :
"");
HTM_TD_End ();
HTM_TR_End ();
}
2014-12-01 23:55:08 +01:00
HTM_TABLE_End ();
2016-10-12 14:02:56 +02:00
/***** Button to save changes *****/
Btn_PutConfirmButton (Txt_Save_changes);
2015-04-11 23:46:21 +02:00
/***** End form *****/
Frm_EndForm ();
2016-11-07 14:12:15 +01:00
/***** End box *****/
Box_BoxEnd ();
2019-03-17 19:37:41 +01:00
2019-03-26 11:53:21 +01:00
/***** End section with settings about notifications *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_End ();
2016-11-07 14:12:15 +01:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-11-16 23:19:52 +01:00
/** Get parameter with the sending of email to notify me that I have msgs. ***/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
static void Ntf_GetParsNotifyEvents (void)
2014-12-01 23:55:08 +01:00
{
Ntf_NotifyEvent_t NotifyEvent;
bool CreateNotifForThisEvent;
2019-03-19 13:22:14 +01:00
Gbl.Usrs.Me.UsrDat.NtfEvents.CreateNotif = 0;
Gbl.Usrs.Me.UsrDat.NtfEvents.SendEmail = 0;
2019-12-15 20:02:34 +01:00
for (NotifyEvent = (Ntf_NotifyEvent_t) 1;
NotifyEvent <= (Ntf_NotifyEvent_t) (Ntf_NUM_NOTIFY_EVENTS - 1);
2014-12-01 23:55:08 +01:00
NotifyEvent++) // 0 is reserved for Ntf_EVENT_UNKNOWN
{
if ((CreateNotifForThisEvent = Par_GetParBool (Ntf_ParNotifMeAboutNotifyEvents[NotifyEvent])))
2019-03-19 13:22:14 +01:00
Gbl.Usrs.Me.UsrDat.NtfEvents.CreateNotif |= (1 << NotifyEvent);
2014-12-01 23:55:08 +01:00
if (CreateNotifForThisEvent)
{
Par_GetParBool (Ntf_ParEmailMeAboutNotifyEvents[NotifyEvent]);
if (Par_GetParBool (Ntf_ParEmailMeAboutNotifyEvents[NotifyEvent]))
2019-03-19 13:22:14 +01:00
Gbl.Usrs.Me.UsrDat.NtfEvents.SendEmail |= (1 << NotifyEvent);
2014-12-01 23:55:08 +01:00
}
}
}
/*****************************************************************************/
2019-03-26 11:53:21 +01:00
/******* Change my setting about sending me notify emails about events *******/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Ntf_ChangeNotifyEvents (void)
{
2019-03-26 11:53:21 +01:00
extern const char *Txt_Your_settings_about_notifications_have_changed;
2014-12-01 23:55:08 +01:00
/***** Get param with whether notify me about events *****/
Ntf_GetParsNotifyEvents ();
2014-12-01 23:55:08 +01:00
2019-03-26 11:53:21 +01:00
/***** Store settings about notify events *****/
Set_DB_UpdateMySettingsAboutNotifyEvents ();
2014-12-01 23:55:08 +01:00
/***** Show message *****/
2019-03-26 11:53:21 +01:00
Ale_ShowAlert (Ale_SUCCESS,Txt_Your_settings_about_notifications_have_changed);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************ Write number of notifications **********************/
/*****************************************************************************/
void Ntf_WriteNumberOfNewNtfs (void)
{
extern const char *Txt_See_notifications;
extern const char *Txt_notification;
extern const char *Txt_notifications;
2015-07-22 13:32:56 +02:00
extern const char *Txt_Notifications;
2014-12-01 23:55:08 +01:00
extern const char *Txt_NOTIF_new_SINGULAR;
extern const char *Txt_NOTIF_new_PLURAL;
unsigned NumUnseenNtfs;
unsigned NumNewNtfs = 0;
/***** Get my number of unseen notifications *****/
if ((NumUnseenNtfs = Ntf_DB_GetNumAllMyUnseenNtfs ()))
NumNewNtfs = Ntf_DB_GetNumMyNewUnseenNtfs ();
2014-12-01 23:55:08 +01:00
2019-10-20 22:00:28 +02:00
/***** Begin form *****/
Frm_BeginForm (ActSeeNewNtf);
2014-12-01 23:55:08 +01:00
/***** Begin link *****/
HTM_BUTTON_Submit_Begin (Txt_See_notifications,"class=\"BT_LINK\"");
2014-12-01 23:55:08 +01:00
/***** Number of unseen notifications *****/
HTM_SPAN_Begin ("id=\"notif_all\"");
HTM_TxtF ("%u&nbsp;%s",NumUnseenNtfs,
NumUnseenNtfs == 1 ? Txt_notification :
Txt_notifications);
HTM_SPAN_End ();
/***** Icon and number of new notifications *****/
if (NumNewNtfs)
{
HTM_BR ();
HTM_IMG (Cfg_URL_ICON_PUBLIC,"bell.svg",Txt_Notifications,
"class=\"ICO16x16 NOTIF_ICO_%s\"",The_GetSuffix ());
HTM_TxtF ("&nbsp;%u",NumNewNtfs);
HTM_SPAN_Begin ("id=\"notif_new\"");
HTM_TxtF ("&nbsp;%s",NumNewNtfs == 1 ? Txt_NOTIF_new_SINGULAR :
Txt_NOTIF_new_PLURAL);
HTM_SPAN_End ();
}
/***** End link *****/
HTM_BUTTON_End ();
2014-12-01 23:55:08 +01:00
2015-04-11 17:33:14 +02:00
/***** End form *****/
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****** Get and show number of users who want to be notified by email ********/
/*****************************************************************************/
void Ntf_GetAndShowNumUsrsPerNotifyEvent (void)
{
extern const char *Hlp_ANALYTICS_Figures_notifications;
extern const char *Txt_FIGURE_TYPES[Fig_NUM_FIGURES];
extern const char *Txt_Event;
extern const char *Txt_NOTIFY_EVENTS_PLURAL[Ntf_NUM_NOTIFY_EVENTS];
extern const char *Txt_Number_of_users;
extern const char *Txt_PERCENT_of_users;
extern const char *Txt_Number_of_events;
extern const char *Txt_Number_of_emails;
extern const char *Txt_Total;
Ntf_NotifyEvent_t NotifyEvent;
char *SubQuery;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumUsrsTotal;
unsigned NumUsrsTotalWhoWantToBeNotifiedByEMailAboutSomeEvent;
unsigned NumUsrs[Ntf_NUM_NOTIFY_EVENTS];
unsigned NumEventsTotal = 0;
unsigned NumEvents[Ntf_NUM_NOTIFY_EVENTS];
unsigned NumMailsTotal = 0;
unsigned NumMails[Ntf_NUM_NOTIFY_EVENTS];
/***** Begin box and table *****/
Box_BoxTableBegin (NULL,Txt_FIGURE_TYPES[Fig_NOTIFY_EVENTS],
NULL,NULL,
Hlp_ANALYTICS_Figures_notifications,Box_NOT_CLOSABLE,2);
/***** Heading row *****/
HTM_TR_Begin (NULL);
HTM_TH (Txt_Event ,HTM_HEAD_LEFT);
HTM_TH (Txt_Number_of_users ,HTM_HEAD_RIGHT);
HTM_TH (Txt_PERCENT_of_users,HTM_HEAD_RIGHT);
HTM_TH (Txt_Number_of_events,HTM_HEAD_RIGHT);
HTM_TH (Txt_Number_of_emails,HTM_HEAD_RIGHT);
HTM_TR_End ();
/***** Get total number of users *****/
NumUsrsTotal = Usr_GetTotalNumberOfUsers ();
/***** Get total number of users who want to be
notified by email on some event, from database *****/
NumUsrsTotalWhoWantToBeNotifiedByEMailAboutSomeEvent =
Usr_DB_GetNumUsrsWhoChoseAnOption ("usr_data.EmailNtfEvents<>0");
/***** For each notify event... *****/
for (NotifyEvent = (Ntf_NotifyEvent_t) 1;
NotifyEvent <= (Ntf_NotifyEvent_t) (Ntf_NUM_NOTIFY_EVENTS - 1);
NotifyEvent++) // 0 is reserved for Ntf_EVENT_UNKNOWN
{
/* Get the number of users who want to be notified by email on this event, from database */
if (asprintf (&SubQuery,"((usr_data.EmailNtfEvents & %u)<>0)",
(1 << NotifyEvent)) < 0)
Err_NotEnoughMemoryExit ();
NumUsrs[NotifyEvent] = Usr_DB_GetNumUsrsWhoChoseAnOption (SubQuery);
free (SubQuery);
/* Get number of notifications by email from database */
if (Ntf_DB_GetNumNotifs (&mysql_res,NotifyEvent))
{
row = mysql_fetch_row (mysql_res);
/* Get number of events notified */
if (row[0])
{
if (sscanf (row[0],"%u",&NumEvents[NotifyEvent]) != 1)
Err_ShowErrorAndExit ("Error when getting the number of notifications by email.");
}
else
NumEvents[NotifyEvent] = 0;
/* Get number of mails sent */
if (row[1])
{
if (sscanf (row[1],"%u",&NumMails[NotifyEvent]) != 1)
Err_ShowErrorAndExit ("Error when getting the number of emails to notify events3.");
}
else
NumMails[NotifyEvent] = 0;
}
else
{
NumEvents[NotifyEvent] = 0;
NumMails[NotifyEvent] = 0;
}
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
/* Update total number of events and mails */
NumEventsTotal += NumEvents[NotifyEvent];
NumMailsTotal += NumMails [NotifyEvent];
}
/***** Write number of users who want to be notified by email on each event *****/
for (NotifyEvent = (Ntf_NotifyEvent_t) 1;
NotifyEvent <= (Ntf_NotifyEvent_t) (Ntf_NUM_NOTIFY_EVENTS - 1);
NotifyEvent++) // 0 is reserved for Ntf_EVENT_UNKNOWN
{
HTM_TR_Begin (NULL);
HTM_TD_Begin ("class=\"LM DAT_%s\"",
The_GetSuffix ());
HTM_Txt (Txt_NOTIFY_EVENTS_PLURAL[NotifyEvent]);
HTM_TD_End ();
HTM_TD_Begin ("class=\"RM DAT_%s\"",
The_GetSuffix ());
HTM_Unsigned (NumUsrs[NotifyEvent]);
HTM_TD_End ();
HTM_TD_Begin ("class=\"RM DAT_%s\"",
The_GetSuffix ());
HTM_Percentage (NumUsrsTotal ? (double) NumUsrs[NotifyEvent] * 100.0 /
(double) NumUsrsTotal :
0.0);
HTM_TD_End ();
HTM_TD_Begin ("class=\"RM DAT_%s\"",
The_GetSuffix ());
HTM_Unsigned (NumEvents[NotifyEvent]);
HTM_TD_End ();
HTM_TD_Begin ("class=\"RM DAT_%s\"",
The_GetSuffix ());
HTM_Unsigned (NumMails[NotifyEvent]);
HTM_TD_End ();
HTM_TR_End ();
}
/***** Write total number of users who want to be notified by email on some event *****/
HTM_TR_Begin (NULL);
HTM_TD_Begin ("class=\"LM DAT_STRONG_%s LINE_TOP\"",
The_GetSuffix ());
HTM_Txt (Txt_Total);
HTM_TD_End ();
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s LINE_TOP\"",
The_GetSuffix ());
HTM_Unsigned (NumUsrsTotalWhoWantToBeNotifiedByEMailAboutSomeEvent);
HTM_TD_End ();
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s LINE_TOP\"",
The_GetSuffix ());
HTM_Percentage (NumUsrsTotal ? (double) NumUsrsTotalWhoWantToBeNotifiedByEMailAboutSomeEvent * 100.0 /
(double) NumUsrsTotal :
0.0);
HTM_TD_End ();
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s LINE_TOP\"",
The_GetSuffix ());
HTM_Unsigned (NumEventsTotal);
HTM_TD_End ();
HTM_TD_Begin ("class=\"RM DAT_STRONG_%s LINE_TOP\"",
The_GetSuffix ());
HTM_Unsigned (NumMailsTotal);
HTM_TD_End ();
HTM_TR_End ();
/***** End table and box *****/
Box_BoxTableEnd ();
}