diff --git a/sql/swad.sql b/sql/swad.sql index f49db02c..506b1ccc 100644 --- a/sql/swad.sql +++ b/sql/swad.sql @@ -1378,6 +1378,7 @@ CREATE TABLE IF NOT EXISTS usr_figures ( UsrCod INT NOT NULL, FirstClickTime DATETIME NOT NULL, NumClicks INT NOT NULL DEFAULT -1, + NumSocPub INT NOT NULL DEFAULT -1, NumFileViews INT NOT NULL DEFAULT -1, NumForPst INT NOT NULL DEFAULT -1, NumMsgSnt INT NOT NULL DEFAULT -1, diff --git a/swad_changelog.h b/swad_changelog.h index 3d9ea6f5..9af60728 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -428,17 +428,20 @@ En OpenSWAD: ps2pdf source.ps destination.pdf */ -#define Log_PLATFORM_VERSION "SWAD 18.64.7 (2019-03-05)" +#define Log_PLATFORM_VERSION "SWAD 18.65 (2019-03-06)" #define CSS_FILE "swad18.64.css" #define JS_FILE "swad18.64.js" /* + Version 18.65: Mar 06, 2019 New user's figure: number of social posts. (238648 lines) + 1 change necessary in database: +ALTER TABLE usr_figures ADD COLUMN NumSocPub INT NOT NULL DEFAULT -1 AFTER NumClicks; + Version 18.64.7: Mar 05, 2019 Changes in user's figures. (238506 lines) Version 18.64.6: Mar 05, 2019 Added non-editing teachers in user's figures. (238525 lines) Version 18.64.5: Mar 05, 2019 Changes writing floating point numbers. For load speed issues, the number of publications by default in the timeline becomes 20 again. The actions in buttons to calculate user's figures are merged in one. (238471 lines) 2 changes necessary in database: - Calcular fecha del primer clic UPDATE actions SET Txt='Calcular cifras de un usuario' WHERE ActCod='1405' AND Language='es'; UPDATE actions SET Obsolete='Y' WHERE ActCod IN (1406,1407,1408,1409); diff --git a/swad_database.c b/swad_database.c index d6c159aa..27f32fe2 100644 --- a/swad_database.c +++ b/swad_database.c @@ -2913,16 +2913,18 @@ mysql> DESCRIBE usr_figures; | UsrCod | int(11) | NO | PRI | NULL | | | FirstClickTime | datetime | NO | MUL | NULL | | | NumClicks | int(11) | NO | MUL | -1 | | +| NumSocPub | int(11) | NO | | -1 | | | NumFileViews | int(11) | NO | | -1 | | | NumForPst | int(11) | NO | | -1 | | | NumMsgSnt | int(11) | NO | | -1 | | +----------------+----------+------+-----+---------+-------+ -6 rows in set (0.01 sec) +7 rows in set (0.01 sec) */ DB_CreateTable ("CREATE TABLE IF NOT EXISTS usr_figures (" "UsrCod INT NOT NULL," "FirstClickTime DATETIME NOT NULL," "NumClicks INT NOT NULL DEFAULT -1," + "NumSocPub INT NOT NULL DEFAULT -1," "NumFileViews INT NOT NULL DEFAULT -1," "NumForPst INT NOT NULL DEFAULT -1," "NumMsgSnt INT NOT NULL DEFAULT -1," diff --git a/swad_exam.c b/swad_exam.c index 40b15086..301614a1 100644 --- a/swad_exam.c +++ b/swad_exam.c @@ -292,7 +292,7 @@ void Exa_ReceiveExamAnnouncement2 (void) extern const char *Txt_Created_new_announcement_of_exam; extern const char *Txt_The_announcement_of_exam_has_been_successfully_updated; unsigned NumUsrsToBeNotifiedByEMail; - struct SocialPublishing SocPub; + struct SocialPublication SocPub; /***** Show message *****/ Ale_ShowAlert (Ale_SUCCESS, diff --git a/swad_file_browser.c b/swad_file_browser.c index 3f20c3a6..15a337c2 100644 --- a/swad_file_browser.c +++ b/swad_file_browser.c @@ -10403,7 +10403,7 @@ void Brw_ChgFileMetadata (void) bool PublicFileBeforeEdition; bool PublicFileAfterEdition; Brw_License_t License; - struct SocialPublishing SocPub; + struct SocialPublication SocPub; /***** Get parameters related to file browser *****/ Brw_GetParAndInitFileBrowser (); diff --git a/swad_forum.c b/swad_forum.c index d99bb250..37f9589e 100644 --- a/swad_forum.c +++ b/swad_forum.c @@ -385,7 +385,7 @@ static void For_RemoveThrCodFromThrClipboard (long ThrCod); void For_EnablePost (void) { - extern const char *Txt_Post_unbanned; + extern const char *Txt_FORUM_Post_unbanned; /***** Get parameters related to forum *****/ For_GetParamsForum (); @@ -401,7 +401,7 @@ void For_EnablePost (void) Ale_SUCCESS,NULL); /***** Show the posts again *****/ - For_ShowPostsOfAThread (Ale_SUCCESS,Txt_Post_unbanned); + For_ShowPostsOfAThread (Ale_SUCCESS,Txt_FORUM_Post_unbanned); } /*****************************************************************************/ @@ -410,7 +410,7 @@ void For_EnablePost (void) void For_DisablePost (void) { - extern const char *Txt_Post_banned; + extern const char *Txt_FORUM_Post_banned; /***** Get parameters related to forum *****/ For_GetParamsForum (); @@ -429,7 +429,7 @@ void For_DisablePost (void) Ale_SUCCESS,NULL); /***** Show the posts again *****/ - For_ShowPostsOfAThread (Ale_SUCCESS,Txt_Post_banned); + For_ShowPostsOfAThread (Ale_SUCCESS,Txt_FORUM_Post_banned); } else Lay_ShowErrorAndExit ("The post to be banned no longer exists."); @@ -872,7 +872,7 @@ static unsigned For_GetNumMyPstInThr (long ThrCod) unsigned long For_GetNumPostsUsr (long UsrCod) { /***** Get number of posts from a user from database *****/ - return DB_QueryCOUNT ("can not number of posts from a user", + return DB_QueryCOUNT ("can not number of forum posts from a user", "SELECT COUNT(*) FROM forum_post" " WHERE UsrCod=%ld", UsrCod); @@ -1149,11 +1149,11 @@ static void For_ShowAForumPost (unsigned PstNum,long PstCod, extern const char *Txt_MSG_New; extern const char *Txt_MSG_Open; extern const char *Txt_no_subject; - extern const char *Txt_Post_X_allowed; - extern const char *Txt_Post_banned; - extern const char *Txt_Post_X_banned; - extern const char *Txt_Post_X_allowed_Click_to_ban_it; - extern const char *Txt_Post_X_banned_Click_to_unban_it; + extern const char *Txt_FORUM_Post_X_allowed; + extern const char *Txt_FORUM_Post_banned; + extern const char *Txt_FORUM_Post_X_banned; + extern const char *Txt_FORUM_Post_X_allowed_Click_to_ban_it; + extern const char *Txt_FORUM_Post_X_banned_Click_to_unban_it; extern const char *Txt_This_post_has_been_banned_probably_for_not_satisfy_the_rules_of_the_forums; struct UsrData UsrDat; time_t CreatTimeUTC; // Creation time of a post @@ -1218,7 +1218,7 @@ static void For_ShowAForumPost (unsigned PstNum,long PstCod, fprintf (Gbl.F.Out,"[%s]",Txt_no_subject); } else - fprintf (Gbl.F.Out,"[%s]",Txt_Post_banned); + fprintf (Gbl.F.Out,"[%s]",Txt_FORUM_Post_banned); fprintf (Gbl.F.Out,"" ""); @@ -1239,8 +1239,8 @@ static void For_ShowAForumPost (unsigned PstNum,long PstCod, PstCod); snprintf (Gbl.Title,sizeof (Gbl.Title), - Enabled ? Txt_Post_X_allowed_Click_to_ban_it : - Txt_Post_X_banned_Click_to_unban_it, + Enabled ? Txt_FORUM_Post_X_allowed_Click_to_ban_it : + Txt_FORUM_Post_X_banned_Click_to_unban_it, PstNum); Ico_PutIconLink (Enabled ? "eye.svg" : "eye-slash.svg", @@ -1250,8 +1250,8 @@ static void For_ShowAForumPost (unsigned PstNum,long PstCod, else { snprintf (Gbl.Title,sizeof (Gbl.Title), - Enabled ? Txt_Post_X_allowed : - Txt_Post_X_banned, + Enabled ? Txt_FORUM_Post_X_allowed : + Txt_FORUM_Post_X_banned, PstNum); fprintf (Gbl.F.Out,"" ""); @@ -2397,8 +2397,8 @@ static void For_WriteNumThrsAndPsts (unsigned NumThrs,unsigned NumThrsWithNewPos { extern const char *Txt_thread; extern const char *Txt_threads; - extern const char *Txt_post; - extern const char *Txt_posts; + extern const char *Txt_FORUM_post; + extern const char *Txt_FORUM_posts; extern const char *Txt_with_new_posts; /***** Write number of threads and number of posts *****/ @@ -2410,16 +2410,16 @@ static void For_WriteNumThrsAndPsts (unsigned NumThrs,unsigned NumThrsWithNewPos fprintf (Gbl.F.Out,", 1 %s",Txt_with_new_posts); fprintf (Gbl.F.Out,"; "); if (NumPosts == 1) - fprintf (Gbl.F.Out,"1 %s",Txt_post); + fprintf (Gbl.F.Out,"1 %s",Txt_FORUM_post); else - fprintf (Gbl.F.Out,"%u %s",NumPosts,Txt_posts); + fprintf (Gbl.F.Out,"%u %s",NumPosts,Txt_FORUM_posts); } else { fprintf (Gbl.F.Out,"%u %s",NumThrs,Txt_threads); if (NumThrsWithNewPosts) fprintf (Gbl.F.Out,", %u %s",NumThrsWithNewPosts,Txt_with_new_posts); - fprintf (Gbl.F.Out,"; %u %s",NumPosts,Txt_posts); + fprintf (Gbl.F.Out,"; %u %s",NumPosts,Txt_FORUM_posts); } fprintf (Gbl.F.Out,"]"); } @@ -4026,11 +4026,11 @@ static void For_WriteFormForumPst (bool IsReply,const char *Subject) void For_ReceiveForumPost (void) { - extern const char *Txt_Post_sent; + extern const char *Txt_FORUM_Post_sent; bool IsReply = false; long PstCod = 0; unsigned NumUsrsToBeNotifiedByEMail; - struct SocialPublishing SocPub; + struct SocialPublication SocPub; char Content[Cns_MAX_BYTES_LONG_TEXT + 1]; struct Media Media; @@ -4129,7 +4129,7 @@ void For_ReceiveForumPost (void) Ale_SUCCESS,NULL); /***** Show again the posts of this thread of the forum *****/ - For_ShowPostsOfAThread (Ale_SUCCESS,Txt_Post_sent); + For_ShowPostsOfAThread (Ale_SUCCESS,Txt_FORUM_Post_sent); } /*****************************************************************************/ @@ -4151,8 +4151,8 @@ static void For_UpdateNumUsrsNotifiedByEMailAboutPost (long PstCod,unsigned NumU void For_RemovePost (void) { - extern const char *Txt_Post_and_thread_removed; - extern const char *Txt_Post_removed; + extern const char *Txt_FORUM_Post_and_thread_removed; + extern const char *Txt_FORUM_Post_removed; struct UsrData UsrDat; time_t CreatTimeUTC; // Creation time of a message char Subject[Cns_MAX_BYTES_SUBJECT + 1]; @@ -4212,14 +4212,14 @@ void For_RemovePost (void) if (ThreadDeleted) /***** Show the remaining threads *****/ For_ShowForumThreadsHighlightingOneThread (Gbl.Forum.ForumSelected.ThrCod, - Ale_SUCCESS,Txt_Post_and_thread_removed); + Ale_SUCCESS,Txt_FORUM_Post_and_thread_removed); else { /***** Show threads again *****/ For_ShowForumThreadsHighlightingOneThread (Gbl.Forum.ForumSelected.ThrCod, Ale_SUCCESS,NULL); /***** Show the remaining posts *****/ - For_ShowPostsOfAThread (Ale_SUCCESS,Txt_Post_removed); + For_ShowPostsOfAThread (Ale_SUCCESS,Txt_FORUM_Post_removed); } } diff --git a/swad_notice.c b/swad_notice.c index 32f6e03c..0676f9fa 100644 --- a/swad_notice.c +++ b/swad_notice.c @@ -130,7 +130,7 @@ void Not_ReceiveNotice (void) extern const char *Txt_Notice_created; long NotCod; unsigned NumUsrsToBeNotifiedByEMail; - struct SocialPublishing SocPub; + struct SocialPublication SocPub; char Content[Cns_MAX_BYTES_TEXT + 1]; /***** Get the text of the notice *****/ diff --git a/swad_notification.c b/swad_notification.c index 2313079b..801d9f5f 100644 --- a/swad_notification.c +++ b/swad_notification.c @@ -896,7 +896,7 @@ void Ntf_GetNotifSummaryAndContent (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1], case Ntf_EVENT_TIMELINE_SHARE: case Ntf_EVENT_TIMELINE_MENTION: // Cod is the code of the social publishing - Soc_GetNotifSocialPublishing (SummaryStr,ContentStr,Cod,GetContent); + Soc_GetNotifSocialPublication (SummaryStr,ContentStr,Cod,GetContent); break; case Ntf_EVENT_FOLLOWER: Fol_GetNotifFollower (SummaryStr,ContentStr); diff --git a/swad_pagination.c b/swad_pagination.c index f883ac1c..7853f842 100644 --- a/swad_pagination.c +++ b/swad_pagination.c @@ -145,7 +145,7 @@ void Pag_WriteLinksToPages (Pag_WhatPaginate_t WhatPaginate, bool LinkToPagCurrent) { extern const char *Txt_Page_X_of_Y; - extern const char *Txt_Post_banned; + extern const char *Txt_FORUM_Post_banned; unsigned NumPage; char LinkStyle[64]; @@ -245,7 +245,7 @@ void Pag_WriteLinksToPages (Pag_WhatPaginate_t WhatPaginate, if (FirstMsgEnabled) fprintf (Gbl.F.Out,"%s",Subject); else - fprintf (Gbl.F.Out,"[%s]",Txt_Post_banned); + fprintf (Gbl.F.Out,"[%s]",Txt_FORUM_Post_banned); if (LinkToPagCurrent) { fprintf (Gbl.F.Out,""); diff --git a/swad_profile.c b/swad_profile.c index 3ac1432d..f8a95129 100644 --- a/swad_profile.c +++ b/swad_profile.c @@ -74,7 +74,7 @@ extern struct Globals Gbl; /***************************** Private prototypes ****************************/ /*****************************************************************************/ -static void Prf_PutLinkCalculateFigures (Act_Action_t Action,const char *EncryptedUsrCod); +static void Prf_PutLinkCalculateFigures (const char *EncryptedUsrCod); static unsigned long Prf_GetRankingFigure (long UsrCod,const char *FieldName); static unsigned long Prf_GetNumUsrsWithFigure (const char *FieldName); @@ -84,9 +84,10 @@ static void Prf_ShowRanking (unsigned long Rank,unsigned long NumUsrs); static void Prf_GetFirstClickFromLogAndStoreAsUsrFigure (long UsrCod); static void Prf_GetNumClicksAndStoreAsUsrFigure (long UsrCod); +static void Prf_GetNumSocialPubsAndStoreAsUsrFigure (long UsrCod); static void Prf_GetNumFileViewsAndStoreAsUsrFigure (long UsrCod); -static void Prf_GetNumForPstAndStoreAsUsrFigure (long UsrCod); -static void Prf_GetNumMsgSntAndStoreAsUsrFigure (long UsrCod); +static void Prf_GetNumForumPostsAndStoreAsUsrFigure (long UsrCod); +static void Prf_GetNumMessagesSentAndStoreAsUsrFigure (long UsrCod); static void Prf_ResetUsrFigures (struct UsrFigures *UsrFigures); static void Prf_CreateUsrFigures (long UsrCod,const struct UsrFigures *UsrFigures, @@ -364,12 +365,15 @@ void Prf_ShowDetailsUserProfile (const struct UsrData *UsrDat) extern const char *Txt_Today; extern const char *Txt_Clicks; extern const char *Txt_clicks; + extern const char *Txt_Timeline; + extern const char *Txt_SOCIAL_post; + extern const char *Txt_SOCIAL_posts; extern const char *Txt_Downloads; extern const char *Txt_download; extern const char *Txt_downloads; extern const char *Txt_Forums; - extern const char *Txt_post; - extern const char *Txt_posts; + extern const char *Txt_FORUM_post; + extern const char *Txt_FORUM_posts; extern const char *Txt_Messages; extern const char *Txt_message; extern const char *Txt_messages; @@ -490,7 +494,7 @@ void Prf_ShowDetailsUserProfile (const struct UsrData *UsrDat) } else // First click time is unknown or user never logged /***** Button to fetch and store user's figures *****/ - Prf_PutLinkCalculateFigures (ActCalFig,UsrDat->EncryptedUsrCod); + Prf_PutLinkCalculateFigures (UsrDat->EncryptedUsrCod); fprintf (Gbl.F.Out,""); /***** End left list *****/ @@ -530,7 +534,34 @@ void Prf_ShowDetailsUserProfile (const struct UsrData *UsrDat) } else // Number of clicks is unknown /***** Button to fetch and store user's figures *****/ - Prf_PutLinkCalculateFigures (ActCalFig,UsrDat->EncryptedUsrCod); + Prf_PutLinkCalculateFigures (UsrDat->EncryptedUsrCod); + fprintf (Gbl.F.Out,""); + + /***** Number of social publications *****/ + fprintf (Gbl.F.Out,"
  • ", + Txt_Timeline, + Gbl.Prefs.URLIcons); + if (UsrFigures.NumSocPub >= 0) + { + fprintf (Gbl.F.Out,"%ld %s ", + UsrFigures.NumSocPub, + (UsrFigures.NumSocPub == 1) ? Txt_SOCIAL_post : + Txt_SOCIAL_posts); + Prf_ShowRanking (Prf_GetRankingFigure (UsrDat->UsrCod,"NumSocPub"), + Prf_GetNumUsrsWithFigure ("NumSocPub")); + if (UsrFigures.NumDays > 0) + { + fprintf (Gbl.F.Out," ("); + Str_WriteFloatNum (Gbl.F.Out, + (float) UsrFigures.NumSocPub / + (float) UsrFigures.NumDays); + fprintf (Gbl.F.Out,"/%s)",Txt_day); + } + } + else // Number of social publications is unknown + /***** Button to fetch and store user's figures *****/ + Prf_PutLinkCalculateFigures (UsrDat->EncryptedUsrCod); fprintf (Gbl.F.Out,"
  • "); /***** Number of file views *****/ @@ -557,7 +588,7 @@ void Prf_ShowDetailsUserProfile (const struct UsrData *UsrDat) } else // Number of file views is unknown /***** Button to fetch and store user's figures *****/ - Prf_PutLinkCalculateFigures (ActCalFig,UsrDat->EncryptedUsrCod); + Prf_PutLinkCalculateFigures (UsrDat->EncryptedUsrCod); fprintf (Gbl.F.Out,""); /***** Number of posts in forums *****/ @@ -569,8 +600,8 @@ void Prf_ShowDetailsUserProfile (const struct UsrData *UsrDat) { fprintf (Gbl.F.Out,"%ld %s ", UsrFigures.NumForPst, - (UsrFigures.NumForPst == 1) ? Txt_post : - Txt_posts); + (UsrFigures.NumForPst == 1) ? Txt_FORUM_post : + Txt_FORUM_posts); Prf_ShowRanking (Prf_GetRankingFigure (UsrDat->UsrCod,"NumForPst"), Prf_GetNumUsrsWithFigure ("NumForPst")); if (UsrFigures.NumDays > 0) @@ -584,7 +615,7 @@ void Prf_ShowDetailsUserProfile (const struct UsrData *UsrDat) } else // Number of forum posts is unknown /***** Button to fetch and store user's figures *****/ - Prf_PutLinkCalculateFigures (ActCalFig,UsrDat->EncryptedUsrCod); + Prf_PutLinkCalculateFigures (UsrDat->EncryptedUsrCod); fprintf (Gbl.F.Out,""); /***** Number of messages sent *****/ @@ -611,7 +642,7 @@ void Prf_ShowDetailsUserProfile (const struct UsrData *UsrDat) } else // Number of messages sent is unknown /***** Button to fetch and store user's figures *****/ - Prf_PutLinkCalculateFigures (ActCalFig,UsrDat->EncryptedUsrCod); + Prf_PutLinkCalculateFigures (UsrDat->EncryptedUsrCod); fprintf (Gbl.F.Out,""); } @@ -624,12 +655,12 @@ void Prf_ShowDetailsUserProfile (const struct UsrData *UsrDat) /******** Put contextual link with animated icon to update an action *********/ /*****************************************************************************/ -static void Prf_PutLinkCalculateFigures (Act_Action_t Action,const char *EncryptedUsrCod) +static void Prf_PutLinkCalculateFigures (const char *EncryptedUsrCod) { extern const char *The_ClassFormOutBoxBold[The_NUM_THEMES]; extern const char *Txt_Calculate; - Frm_StartForm (Action); + Frm_StartForm (ActCalFig); Usr_PutParamUsrCodEncrypted (EncryptedUsrCod); Frm_LinkFormSubmitAnimated (Txt_Calculate, The_ClassFormOutBoxBold[Gbl.Prefs.Theme], @@ -650,9 +681,13 @@ void Prf_GetUsrFigures (long UsrCod,struct UsrFigures *UsrFigures) /***** Get user's figures from database *****/ NumRows = (unsigned) DB_QuerySELECT (&mysql_res,"can not get user's figures", - "SELECT UNIX_TIMESTAMP(FirstClickTime)," - "DATEDIFF(NOW(),FirstClickTime)+1," - "NumClicks,NumFileViews,NumForPst,NumMsgSnt" + "SELECT UNIX_TIMESTAMP(FirstClickTime)," // row[0] + "DATEDIFF(NOW(),FirstClickTime)+1," // row[1] + "NumClicks," // row[2] + "NumSocPub," // row[3] + "NumFileViews," // row[4] + "NumForPst," // row[5] + "NumMsgSnt" // row[6] " FROM usr_figures WHERE UsrCod=%ld", UsrCod); if (NumRows) @@ -676,16 +711,20 @@ void Prf_GetUsrFigures (long UsrCod,struct UsrFigures *UsrFigures) if (sscanf (row[2],"%ld",&UsrFigures->NumClicks) != 1) UsrFigures->NumClicks = -1L; - /* Get number of file views (row[3]) */ - if (sscanf (row[3],"%ld",&UsrFigures->NumFileViews) != 1) + /* Get number of social publications (row[3]) */ + if (sscanf (row[3],"%ld",&UsrFigures->NumSocPub) != 1) + UsrFigures->NumSocPub = -1L; + + /* Get number of file views (row[4]) */ + if (sscanf (row[4],"%ld",&UsrFigures->NumFileViews) != 1) UsrFigures->NumFileViews = -1L; - /* Get number of forum posts (row[4]) */ - if (sscanf (row[4],"%ld",&UsrFigures->NumForPst) != 1) + /* Get number of forum posts (row[5]) */ + if (sscanf (row[5],"%ld",&UsrFigures->NumForPst) != 1) UsrFigures->NumForPst = -1L; - /* Get number of messages sent (row[5]) */ - if (sscanf (row[5],"%ld",&UsrFigures->NumMsgSnt) != 1) + /* Get number of messages sent (row[6]) */ + if (sscanf (row[6],"%ld",&UsrFigures->NumMsgSnt) != 1) UsrFigures->NumMsgSnt = -1L; } else @@ -828,6 +867,12 @@ bool Prf_GetAndStoreAllUsrFigures (long UsrCod,struct UsrFigures *UsrFigures) Prf_GetNumClicksAndStoreAsUsrFigure (UsrCod); UsrFiguresModified = true; } + if (UsrFigures->NumSocPub < 0) + { + /***** Get number of social publications and store as user's figure *****/ + Prf_GetNumSocialPubsAndStoreAsUsrFigure (UsrCod); + UsrFiguresModified = true; + } if (UsrFigures->NumFileViews < 0) { /***** Get number of file views and store as user's figure *****/ @@ -837,13 +882,13 @@ bool Prf_GetAndStoreAllUsrFigures (long UsrCod,struct UsrFigures *UsrFigures) if (UsrFigures->NumForPst < 0) { /***** Get number of forum posts and store as user's figure *****/ - Prf_GetNumForPstAndStoreAsUsrFigure (UsrCod); + Prf_GetNumForumPostsAndStoreAsUsrFigure (UsrCod); UsrFiguresModified = true; } if (UsrFigures->NumMsgSnt < 0) { /***** Get number of messages sent and store as user's figure *****/ - Prf_GetNumMsgSntAndStoreAsUsrFigure (UsrCod); + Prf_GetNumMessagesSentAndStoreAsUsrFigure (UsrCod); UsrFiguresModified = true; } @@ -924,7 +969,34 @@ static void Prf_GetNumClicksAndStoreAsUsrFigure (long UsrCod) else // User entry does not exist Prf_CreateUsrFigures (UsrCod,&UsrFigures,false); } - } + } + +/*****************************************************************************/ +/* Get number of social publications from a user and store in user's figures */ +/*****************************************************************************/ + +static void Prf_GetNumSocialPubsAndStoreAsUsrFigure (long UsrCod) + { + struct UsrFigures UsrFigures; + + if (Usr_ChkIfUsrCodExists (UsrCod)) + { + /***** Reset user's figures *****/ + Prf_ResetUsrFigures (&UsrFigures); + + /***** Get number of forum posts from database *****/ + UsrFigures.NumSocPub = Soc_GetNumPubsUsr (UsrCod); + + /***** Update number of forum posts in user's figures *****/ + if (Prf_CheckIfUsrFiguresExists (UsrCod)) + DB_QueryUPDATE ("can not update user's figures", + "UPDATE usr_figures SET NumSocPub=%ld" + " WHERE UsrCod=%ld", + UsrFigures.NumSocPub,UsrCod); + else // User entry does not exist + Prf_CreateUsrFigures (UsrCod,&UsrFigures,false); + } + } /*****************************************************************************/ /**** Get number of file views sent by a user and store in user's figures ****/ @@ -951,13 +1023,13 @@ static void Prf_GetNumFileViewsAndStoreAsUsrFigure (long UsrCod) else // User entry does not exist Prf_CreateUsrFigures (UsrCod,&UsrFigures,false); } - } + } /*****************************************************************************/ /**** Get number of forum posts sent by a user and store in user's figures ***/ /*****************************************************************************/ -static void Prf_GetNumForPstAndStoreAsUsrFigure (long UsrCod) +static void Prf_GetNumForumPostsAndStoreAsUsrFigure (long UsrCod) { struct UsrFigures UsrFigures; @@ -978,13 +1050,13 @@ static void Prf_GetNumForPstAndStoreAsUsrFigure (long UsrCod) else // User entry does not exist Prf_CreateUsrFigures (UsrCod,&UsrFigures,false); } - } + } /*****************************************************************************/ /***** Get number of messages sent by a user and store in user's figures *****/ /*****************************************************************************/ -static void Prf_GetNumMsgSntAndStoreAsUsrFigure (long UsrCod) +static void Prf_GetNumMessagesSentAndStoreAsUsrFigure (long UsrCod) { struct UsrFigures UsrFigures; @@ -1018,6 +1090,7 @@ void Prf_CreateNewUsrFigures (long UsrCod,bool CreatingMyOwnAccount) /***** Reset user's figures *****/ Prf_ResetUsrFigures (&UsrFigures); UsrFigures.NumClicks = 0; // set number of clicks to 0 + UsrFigures.NumSocPub = 0; // set number of social publications to 0 UsrFigures.NumFileViews = 0; // set number of file views to 0 UsrFigures.NumForPst = 0; // set number of forum posts to 0 UsrFigures.NumMsgSnt = 0; // set number of messages sent to 0 @@ -1035,6 +1108,7 @@ static void Prf_ResetUsrFigures (struct UsrFigures *UsrFigures) UsrFigures->FirstClickTimeUTC = (time_t) 0; // unknown first click time or user never logged UsrFigures->NumDays = -1; // not applicable UsrFigures->NumClicks = -1L; // unknown number of clicks + UsrFigures->NumSocPub = -1L; // unknown number of social publications UsrFigures->NumFileViews = -1L; // unknown number of file views UsrFigures->NumForPst = -1L; // unknown number of forum posts UsrFigures->NumMsgSnt = -1L; // unknown number of messages sent @@ -1062,12 +1136,13 @@ static void Prf_CreateUsrFigures (long UsrCod,const struct UsrFigures *UsrFigure /***** Create user's figures *****/ DB_QueryINSERT ("can not create user's figures", "INSERT INTO usr_figures" - " (UsrCod,FirstClickTime,NumClicks,NumFileViews,NumForPst,NumMsgSnt)" + " (UsrCod,FirstClickTime,NumClicks,NumSocPub,NumFileViews,NumForPst,NumMsgSnt)" " VALUES" - " (%ld,%s,%ld,%ld,%ld,%ld)", + " (%ld,%s,%ld,%ld,%ld,%ld,%ld)", UsrCod, SubQueryFirstClickTime, UsrFigures->NumClicks, // -1L ==> unknown number of clicks + UsrFigures->NumSocPub, // -1L ==> unknown number of social publications UsrFigures->NumFileViews, // -1L ==> unknown number of file views UsrFigures->NumForPst, // -1L ==> unknown number of forum posts UsrFigures->NumMsgSnt); // -1L ==> unknown number of messages sent @@ -1111,6 +1186,20 @@ void Prf_IncrementNumClicksUsr (long UsrCod) UsrCod); } +/*****************************************************************************/ +/********* Increment number of social publications sent by a user ************/ +/*****************************************************************************/ + +void Prf_IncrementNumSocPubUsr (long UsrCod) + { + /***** Increment number of social publications *****/ + // If NumSocPub < 0 ==> not yet calculated, so do nothing + DB_QueryINSERT ("can not increment user's social publications", + "UPDATE IGNORE usr_figures SET NumSocPub=NumSocPub+1" + " WHERE UsrCod=%ld AND NumSocPub>=0", + UsrCod); + } + /*****************************************************************************/ /************** Increment number of file views sent by a user ****************/ /*****************************************************************************/ diff --git a/swad_profile.h b/swad_profile.h index 0c67f71a..aa834138 100644 --- a/swad_profile.h +++ b/swad_profile.h @@ -40,6 +40,7 @@ struct UsrFigures time_t FirstClickTimeUTC; // 0 ==> unknown first click time of user never logged int NumDays; // -1 ==> not applicable long NumClicks; // -1L ==> unknown number of clicks + long NumSocPub; // -1L ==> unknown number of social publications long NumFileViews; // -1L ==> unknown number of file views long NumForPst; // -1L ==> unknown number of forum posts long NumMsgSnt; // -1L ==> unknown number of messages sent @@ -69,6 +70,7 @@ bool Prf_GetAndStoreAllUsrFigures (long UsrCod,struct UsrFigures *UsrFigures); void Prf_CreateNewUsrFigures (long UsrCod,bool CreatingMyOwnAccount); void Prf_RemoveUsrFigures (long UsrCod); void Prf_IncrementNumClicksUsr (long UsrCod); +void Prf_IncrementNumSocPubUsr (long UsrCod); void Prf_IncrementNumFileViewsUsr (long UsrCod); void Prf_IncrementNumForPstUsr (long UsrCod); void Prf_IncrementNumMsgSntUsr (long UsrCod); diff --git a/swad_report.c b/swad_report.c index deead9b9..083a61f3 100644 --- a/swad_report.c +++ b/swad_report.c @@ -600,8 +600,8 @@ static void Rep_WriteSectionUsrFigures (const struct Rep_Report *Report) extern const char *Txt_download; extern const char *Txt_downloads; extern const char *Txt_Forum_posts; - extern const char *Txt_post; - extern const char *Txt_posts; + extern const char *Txt_FORUM_post; + extern const char *Txt_FORUM_posts; extern const char *Txt_Messages_sent; extern const char *Txt_message; extern const char *Txt_messages; @@ -705,8 +705,8 @@ static void Rep_WriteSectionUsrFigures (const struct Rep_Report *Report) { fprintf (Gbl.F.Rep,"%ld %s", Report->UsrFigures.NumForPst, - (Report->UsrFigures.NumForPst == 1) ? Txt_post : - Txt_posts); + (Report->UsrFigures.NumForPst == 1) ? Txt_FORUM_post : + Txt_FORUM_posts); if (Report->UsrFigures.NumDays > 0) { fprintf (Gbl.F.Rep," ("); diff --git a/swad_social.c b/swad_social.c index bb903b94..05aa74f7 100644 --- a/swad_social.c +++ b/swad_social.c @@ -71,11 +71,11 @@ typedef enum typedef enum { - Soc_GET_ONLY_NEW_PUBS, // New publishings are retrieved via AJAX + Soc_GET_ONLY_NEW_PUBS, // New publications are retrieved via AJAX // automatically from time to time Soc_GET_RECENT_TIMELINE, // Recent timeline is shown when user clicks on action menu,... // or after editing timeline - Soc_GET_ONLY_OLD_PUBS, // Old publishings are retrieved via AJAX + Soc_GET_ONLY_OLD_PUBS, // Old publications are retrieved via AJAX // when user clicks on link at bottom of timeline } Soc_WhatToGetFromTimeline_t; @@ -163,10 +163,10 @@ static void Soc_ShowWarningYouDontFollowAnyUser (void); static void Soc_InsertNewPubsInTimeline (char *Query); static void Soc_ShowOldPubsInTimeline (char *Query); -static void Soc_GetDataOfSocialPublishingFromRow (MYSQL_ROW row,struct SocialPublishing *SocPub); +static void Soc_GetDataOfSocialPublicationFromRow (MYSQL_ROW row,struct SocialPublication *SocPub); -static void Soc_PutLinkToViewNewPublishings (void); -static void Soc_PutLinkToViewOldPublishings (void); +static void Soc_PutLinkToViewNewPublications (void); +static void Soc_PutLinkToViewOldPublications (void); static void Soc_WriteSocialNote (const struct SocialNote *SocNot, Soc_TopMessage_t TopMessage,long UsrCod, @@ -179,7 +179,7 @@ static void Soc_GetAndWriteSocialPost (long PstCod); static void Soc_PutFormGoToAction (const struct SocialNote *SocNot); static void Soc_GetNoteSummary (const struct SocialNote *SocNot, char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1]); -static void Soc_PublishSocialNoteInTimeline (struct SocialPublishing *SocPub); +static void Soc_PublishSocialNoteInTimeline (struct SocialPublication *SocPub); static void Soc_PutFormToWriteNewPost (void); static void Soc_PutTextarea (const char *Placeholder, @@ -213,7 +213,7 @@ static void Soc_PutFormToUnfavSocialNote (const struct SocialNote *SocNot); static void Soc_PutFormToFavSocialComment (struct SocialComment *SocCom); static void Soc_PutFormToUnfavSocialComment (struct SocialComment *SocCom); -static void Soc_PutFormToRemoveSocialPublishing (long NotCod); +static void Soc_PutFormToRemoveSocialPublication (long NotCod); static void Soc_PutHiddenParamNotCod (long NotCod); static long Soc_GetParamNotCod (void); @@ -237,7 +237,7 @@ static void Soc_RemoveSocialNote (void); static void Soc_RemoveImgFileFromSocialPost (long PstCod); static void Soc_RemoveASocialNoteFromDB (struct SocialNote *SocNot); -static long Soc_GetNotCodOfSocialPublishing (long PubCod); +static long Soc_GetNotCodOfSocialPublication (long PubCod); static long Soc_GetPubCodOfOriginalSocialNote (long NotCod); static void Soc_RequestRemovalSocialComment (void); @@ -263,7 +263,7 @@ static void Soc_ShowSharersOrFavers (MYSQL_RES **mysql_res, static void Soc_GetDataOfSocialNotByCod (struct SocialNote *SocNot); static void Soc_GetDataOfSocialComByCod (struct SocialComment *SocCom); -static void Soc_GetDataOfSocialPublishingFromRow (MYSQL_ROW row,struct SocialPublishing *SocPub); +static void Soc_GetDataOfSocialPublicationFromRow (MYSQL_ROW row,struct SocialPublication *SocPub); static void Soc_GetDataOfSocialNoteFromRow (MYSQL_ROW row,struct SocialNote *SocNot); static Soc_PubType_t Soc_GetPubTypeFromStr (const char *Str); static Soc_NoteType_t Soc_GetNoteTypeFromStr (const char *Str); @@ -357,13 +357,13 @@ void Soc_ShowTimelineGbl2 (void) /***** Initialize social note code to -1 ==> no highlighted note *****/ SocNot.NotCod = -1L; - /***** Get parameter with the code of a social publishing *****/ + /***** Get parameter with the code of a social publication *****/ // This parameter is optional. It can be provided by a notification. // If > 0 ==> the social note is shown highlighted above the timeline PubCod = Soc_GetParamPubCod (); if (PubCod > 0) /***** Get code of social note from database *****/ - SocNot.NotCod = Soc_GetNotCodOfSocialPublishing (PubCod); + SocNot.NotCod = Soc_GetNotCodOfSocialPublication (PubCod); if (SocNot.NotCod > 0) { @@ -415,7 +415,7 @@ static void Soc_ShowTimelineUsrHighlightingNot (long NotCod) extern const char *Txt_Timeline_OF_A_USER; char *Query = NULL; - /***** Build query to show timeline with publishings of a unique user *****/ + /***** Build query to show timeline with publications of a unique user *****/ Soc_BuildQueryToGetTimeline (&Query, Soc_TIMELINE_USR, Soc_GET_RECENT_TIMELINE); @@ -431,7 +431,7 @@ static void Soc_ShowTimelineUsrHighlightingNot (long NotCod) } /*****************************************************************************/ -/********** Refresh new publishings in social timeline via AJAX **************/ +/********** Refresh new publications in social timeline via AJAX *************/ /*****************************************************************************/ void Soc_RefreshNewTimelineGbl (void) @@ -464,7 +464,7 @@ void Soc_RefreshNewTimelineGbl (void) } /*****************************************************************************/ -/************ View old publishings in social timeline via AJAX ***************/ +/************ View old publications in social timeline via AJAX **************/ /*****************************************************************************/ void Soc_RefreshOldTimelineGbl (void) @@ -472,7 +472,7 @@ void Soc_RefreshOldTimelineGbl (void) /***** Get which users *****/ Soc_GetParamsWhichUsrs (); - /***** Show old publishings *****/ + /***** Show old publications *****/ Soc_GetAndShowOldTimeline (Soc_TIMELINE_GBL); } @@ -480,12 +480,12 @@ void Soc_RefreshOldTimelineUsr (void) { /***** Get user whom profile is displayed *****/ if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ()) // Existing user - /***** If user exists, show old publishings *****/ + /***** If user exists, show old publications *****/ Soc_GetAndShowOldTimeline (Soc_TIMELINE_USR); } /*****************************************************************************/ -/**************** Get and show old publishings in timeline *******************/ +/**************** Get and show old publications in timeline ******************/ /*****************************************************************************/ static void Soc_GetAndShowOldTimeline (Soc_TimelineUsrOrGbl_t TimelineUsrOrGbl) @@ -559,7 +559,7 @@ static void Soc_BuildQueryToGetTimeline (char **Query, /***** Drop temporary tables *****/ Soc_DropTemporaryTablesUsedToQueryTimeline (); - /***** Create temporary table with publishing codes *****/ + /***** Create temporary table with publication codes *****/ DB_Query ("can not create temporary table", "CREATE TEMPORARY TABLE pub_codes " "(PubCod BIGINT NOT NULL,UNIQUE INDEX(PubCod)) ENGINE=MEMORY"); @@ -650,7 +650,7 @@ static void Soc_BuildQueryToGetTimeline (char **Query, break; } - /***** Get the publishings in timeline *****/ + /***** Get the publications in timeline *****/ /* Initialize range of pubs: social_pubs @@ -672,33 +672,33 @@ static void Soc_BuildQueryToGetTimeline (char **Query, RangePubsToGet.Bottom = 0; // -Infinite switch (WhatToGetFromTimeline) { - case Soc_GET_ONLY_NEW_PUBS: // Get the publishings (without limit) newer than LastPubCod + case Soc_GET_ONLY_NEW_PUBS: // Get the publications (without limit) newer than LastPubCod /* This query is made via AJAX automatically from time to time */ RangePubsToGet.Bottom = Soc_GetPubCodFromSession ("LastPubCod"); break; - case Soc_GET_RECENT_TIMELINE: // Get some limited recent publishings + case Soc_GET_RECENT_TIMELINE: // Get some limited recent publications /* This is the first query to get initial timeline shown ==> no notes yet in current timeline table */ break; - case Soc_GET_ONLY_OLD_PUBS: // Get some limited publishings older than FirstPubCod + case Soc_GET_ONLY_OLD_PUBS: // Get some limited publications older than FirstPubCod /* This query is made via AJAX - when I click in link to get old publishings */ + when I click in link to get old publications */ RangePubsToGet.Top = Soc_GetPubCodFromSession ("FirstPubCod"); break; } /* With the current approach, we select one by one - the publishings and notes in a loop. In each iteration, - we get the more recent publishing (original, shared or commment) - of every set of publishings corresponding to the same note, + the publications and notes in a loop. In each iteration, + we get the more recent publication (original, shared or commment) + of every set of publications corresponding to the same note, checking that the note is not already retrieved. - After getting a publishing, its note code is stored + After getting a publication, its note code is stored in order to not get it again. As an alternative, we tried to get the maximum PubCod, - i.e more recent publishing (original, shared or commment), - of every set of publishings corresponding to the same note: + i.e more recent publication (original, shared or commment), + of every set of publications corresponding to the same note: "SELECT MAX(PubCod) AS NewestPubCod FROM social_pubs ... " GROUP BY NotCod ORDER BY NewestPubCod DESC LIMIT ..." but this query is slow (several seconds) with a big table. @@ -707,7 +707,7 @@ static void Soc_BuildQueryToGetTimeline (char **Query, NumPub < MaxPubsToGet[WhatToGetFromTimeline]; NumPub++) { - /* Create subqueries with range of publishings to get from social_pubs */ + /* Create subqueries with range of publications to get from social_pubs */ if (RangePubsToGet.Bottom > 0) switch (TimelineUsrOrGbl) { @@ -756,13 +756,13 @@ static void Soc_BuildQueryToGetTimeline (char **Query, else SubQueryRangeTop[0] = '\0'; - /* Select the most recent publishing from social_pubs */ + /* Select the most recent publication from social_pubs */ NumPubs = 0; // Initialized to avoid warning switch (TimelineUsrOrGbl) { case Soc_TIMELINE_USR: // Show the timeline of a user NumPubs = - (unsigned) DB_QuerySELECT (&mysql_res,"can not get publishing", + (unsigned) DB_QuerySELECT (&mysql_res,"can not get publication", "SELECT PubCod,NotCod FROM social_pubs" " WHERE %s%s%s%s" " ORDER BY PubCod DESC LIMIT 1", @@ -775,7 +775,7 @@ static void Soc_BuildQueryToGetTimeline (char **Query, { case Soc_USRS_FOLLOWED: // Show the timeline of the users I follow NumPubs = - (unsigned) DB_QuerySELECT (&mysql_res,"can not get publishing", + (unsigned) DB_QuerySELECT (&mysql_res,"can not get publication", "SELECT PubCod,NotCod FROM social_pubs,publishers" " WHERE %s%s%s%s" " ORDER BY social_pubs.PubCod DESC LIMIT 1", @@ -785,7 +785,7 @@ static void Soc_BuildQueryToGetTimeline (char **Query, break; case Soc_USRS_ALL: // Show the timeline of all users NumPubs = - (unsigned) DB_QuerySELECT (&mysql_res,"can not get publishing", + (unsigned) DB_QuerySELECT (&mysql_res,"can not get publication", "SELECT PubCod,NotCod FROM social_pubs" " WHERE %s%s%s" " ORDER BY PubCod DESC LIMIT 1", @@ -801,7 +801,7 @@ static void Soc_BuildQueryToGetTimeline (char **Query, if (NumPubs == 1) { - /* Get code of social publishing */ + /* Get code of social publication */ row = mysql_fetch_row (mysql_res); PubCod = Str_ConvertStrCodToLongCod (row[0]); } @@ -816,7 +816,7 @@ static void Soc_BuildQueryToGetTimeline (char **Query, if (PubCod > 0) { - DB_QueryINSERT ("can not store publishing code", + DB_QueryINSERT ("can not store publication code", "INSERT INTO pub_codes SET PubCod=%ld", PubCod); RangePubsToGet.Top = PubCod; // Narrow the range for the next iteration @@ -834,12 +834,12 @@ static void Soc_BuildQueryToGetTimeline (char **Query, } } else // Nothing got ==> abort loop - break; // Last publishing + break; // Last publication } - /***** Update last publishing code into session for next refresh *****/ - // Do this inmediately after getting the publishings codes... - // ...in order to not lose publishings + /***** Update last publication code into session for next refresh *****/ + // Do this inmediately after getting the publications codes... + // ...in order to not lose publications Soc_UpdateLastPubCodIntoSession (); /***** Add notes just retrieved to current timeline for this session *****/ @@ -854,7 +854,7 @@ static void Soc_BuildQueryToGetTimeline (char **Query, } /*****************************************************************************/ -/********* Get last/first social publishing code stored in session ***********/ +/********* Get last/first social publication code stored in session **********/ /*****************************************************************************/ // FieldName can be: // "LastPubCod" @@ -867,13 +867,13 @@ static long Soc_GetPubCodFromSession (const char *FieldName) MYSQL_ROW row; long PubCod; - /***** Get last publishing code from database *****/ - if (DB_QuerySELECT (&mysql_res,"can not get publishing code from session", + /***** Get last publication code from database *****/ + if (DB_QuerySELECT (&mysql_res,"can not get publication code from session", "SELECT %s FROM sessions WHERE SessionId='%s'", FieldName,Gbl.Session.Id) != 1) Lay_ShowErrorAndExit (Txt_The_session_has_expired); - /***** Get last publishing code *****/ + /***** Get last publication code *****/ row = mysql_fetch_row (mysql_res); if (sscanf (row[0],"%ld",&PubCod) != 1) PubCod = 0; @@ -885,13 +885,13 @@ static long Soc_GetPubCodFromSession (const char *FieldName) } /*****************************************************************************/ -/*********************** Update last publishing code *************************/ +/*********************** Update last publication code ************************/ /*****************************************************************************/ static void Soc_UpdateLastPubCodIntoSession (void) { - /***** Update last publishing code *****/ - DB_QueryUPDATE ("can not update last publishing code into session", + /***** Update last publication code *****/ + DB_QueryUPDATE ("can not update last publication code into session", "UPDATE sessions" " SET LastPubCod=" "(SELECT IFNULL(MAX(PubCod),0) FROM social_pubs)" @@ -900,13 +900,13 @@ static void Soc_UpdateLastPubCodIntoSession (void) } /*****************************************************************************/ -/*********************** Update first publishing code ************************/ +/*********************** Update first publication code ***********************/ /*****************************************************************************/ static void Soc_UpdateFirstPubCodIntoSession (long FirstPubCod) { - /***** Update last publishing code *****/ - DB_QueryUPDATE ("can not update first publishing code into session", + /***** Update last publication code *****/ + DB_QueryUPDATE ("can not update first publication code into session", "UPDATE sessions SET FirstPubCod=%ld WHERE SessionId='%s'", FirstPubCod,Gbl.Session.Id); } @@ -962,12 +962,12 @@ static void Soc_ShowTimeline (char *Query, MYSQL_ROW row; unsigned long NumPubsGot; unsigned long NumPub; - struct SocialPublishing SocPub; + struct SocialPublication SocPub; struct SocialNote SocNot; bool GlobalTimeline = (Gbl.Usrs.Other.UsrDat.UsrCod <= 0); bool ItsMe = Usr_ItsMe (Gbl.Usrs.Other.UsrDat.UsrCod); - /***** Get publishings from database *****/ + /***** Get publications from database *****/ NumPubsGot = DB_QuerySELECT (&mysql_res,"can not get timeline", "%s", Query); @@ -984,29 +984,29 @@ static void Soc_ShowTimeline (char *Query, if (GlobalTimeline || ItsMe) Soc_PutFormToWriteNewPost (); - /***** New publishings refreshed dynamically via AJAX *****/ + /***** New publications refreshed dynamically via AJAX *****/ if (GlobalTimeline) { - /* Link to view new publishings via AJAX */ - Soc_PutLinkToViewNewPublishings (); + /* Link to view new publications via AJAX */ + Soc_PutLinkToViewNewPublications (); - /* Hidden list where insert just received (not visible) publishings via AJAX */ + /* Hidden list where insert just received (not visible) publications via AJAX */ fprintf (Gbl.F.Out,""); - /* Hidden list where insert new (not visible) publishings via AJAX */ + /* Hidden list where insert new (not visible) publications via AJAX */ fprintf (Gbl.F.Out,""); } - /***** List recent publishings in timeline *****/ + /***** List recent publications in timeline *****/ fprintf (Gbl.F.Out,"