Version 15.127

This commit is contained in:
Antonio Cañas Vargas 2016-01-25 11:43:14 +01:00
parent 5ad6d494aa
commit cdd34d0d7f
8 changed files with 155 additions and 54 deletions

View File

@ -121,19 +121,20 @@
// TODO: When receiving a new post, create first the publishing, then the post
// TODO: Change PstCod to PubCod in social_posts, removing AUTO_INCREMENT
// TODO: View highlighted social note when clicking in timeline notification
// TODO: Mark timeline notifications as removed when post/comment are removed or fav/share are undone
// TODO: Mark timeline notifications as removed when unfav/unshared?
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
#define Log_PLATFORM_VERSION "SWAD 15.126.1 (2016-01-24)"
#define Log_PLATFORM_VERSION "SWAD 15.127 (2016-01-24)"
#define CSS_FILE "swad15.121.7.css"
#define JS_FILE "swad15.121.7.js"
// Number of lines (includes comments but not blank lines) has been got with the following command:
// nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*.h sql/swad*.sql | tail -1
/*
Version 15.127: Jan 24, 2016 New function to count the number of @nicknames in a text and store it in social publishing. (194825 lines)
Version 15.126.1: Jan 24, 2016 Optimization in code to insert links. (194736 lines)
Version 15.126: Jan 24, 2016 In any text where URL is replaced by anchor, now @nickname is also replaced to link to user's profile. (194727 lines)
2 changes necessary in database:

View File

@ -279,6 +279,7 @@ void Exa_ReceiveExamAnnouncement (void)
long ExaCod;
bool NewExamAnnouncement;
unsigned NumUsrsToBeNotifiedByEMail;
struct SocialPublishing SocPub;
/***** Allocate memory for the exam announcement *****/
Exa_AllocMemExamAnnouncement ();
@ -306,7 +307,7 @@ void Exa_ReceiveExamAnnouncement (void)
Ntf_ShowAlertNumUsrsToBeNotifiedByEMail (NumUsrsToBeNotifiedByEMail);
/***** Create a new social note about the new exam announcement *****/
Soc_StoreAndPublishSocialNote (Soc_NOTE_EXAM_ANNOUNCEMENT,ExaCod);
Soc_StoreAndPublishSocialNote (Soc_NOTE_EXAM_ANNOUNCEMENT,ExaCod,&SocPub);
/***** Show exam announcement *****/
Exa_ListExamAnnouncementsEdit ();

View File

@ -9642,6 +9642,7 @@ void Brw_ChgFileMetadata (void)
bool PublicFileBeforeEdition;
bool PublicFileAfterEdition;
Brw_License_t License;
struct SocialPublishing SocPub;
/***** Get parameters related to file browser *****/
Brw_GetParAndInitFileBrowser ();
@ -9707,28 +9708,28 @@ void Brw_ChgFileMetadata (void)
switch (Gbl.FileBrowser.Type)
{
case Brw_ADMI_DOCUM_INS:
Soc_StoreAndPublishSocialNote (Soc_NOTE_INS_DOC_PUB_FILE,FileMetadata.FilCod);
Soc_StoreAndPublishSocialNote (Soc_NOTE_INS_DOC_PUB_FILE,FileMetadata.FilCod,&SocPub);
break;
case Brw_ADMI_SHARE_INS:
Soc_StoreAndPublishSocialNote (Soc_NOTE_INS_SHA_PUB_FILE,FileMetadata.FilCod);
Soc_StoreAndPublishSocialNote (Soc_NOTE_INS_SHA_PUB_FILE,FileMetadata.FilCod,&SocPub);
break;
case Brw_ADMI_DOCUM_CTR:
Soc_StoreAndPublishSocialNote (Soc_NOTE_CTR_DOC_PUB_FILE,FileMetadata.FilCod);
Soc_StoreAndPublishSocialNote (Soc_NOTE_CTR_DOC_PUB_FILE,FileMetadata.FilCod,&SocPub);
break;
case Brw_ADMI_SHARE_CTR:
Soc_StoreAndPublishSocialNote (Soc_NOTE_CTR_SHA_PUB_FILE,FileMetadata.FilCod);
Soc_StoreAndPublishSocialNote (Soc_NOTE_CTR_SHA_PUB_FILE,FileMetadata.FilCod,&SocPub);
break;
case Brw_ADMI_DOCUM_DEG:
Soc_StoreAndPublishSocialNote (Soc_NOTE_DEG_DOC_PUB_FILE,FileMetadata.FilCod);
Soc_StoreAndPublishSocialNote (Soc_NOTE_DEG_DOC_PUB_FILE,FileMetadata.FilCod,&SocPub);
break;
case Brw_ADMI_SHARE_DEG:
Soc_StoreAndPublishSocialNote (Soc_NOTE_DEG_SHA_PUB_FILE,FileMetadata.FilCod);
Soc_StoreAndPublishSocialNote (Soc_NOTE_DEG_SHA_PUB_FILE,FileMetadata.FilCod,&SocPub);
break;
case Brw_ADMI_DOCUM_CRS:
Soc_StoreAndPublishSocialNote (Soc_NOTE_CRS_DOC_PUB_FILE,FileMetadata.FilCod);
Soc_StoreAndPublishSocialNote (Soc_NOTE_CRS_DOC_PUB_FILE,FileMetadata.FilCod,&SocPub);
break;
case Brw_ADMI_SHARE_CRS:
Soc_StoreAndPublishSocialNote (Soc_NOTE_CRS_SHA_PUB_FILE,FileMetadata.FilCod);
Soc_StoreAndPublishSocialNote (Soc_NOTE_CRS_SHA_PUB_FILE,FileMetadata.FilCod,&SocPub);
break;
default:
break;

View File

@ -3746,6 +3746,7 @@ void For_RecForumPst (void)
long ThrCod = 0;
long PstCod = 0;
unsigned NumUsrsToBeNotifiedByEMail;
struct SocialPublishing SocPub;
char Content[Cns_MAX_BYTES_LONG_TEXT+1];
/***** Get order type, degree and course of the forum *****/
@ -3834,7 +3835,7 @@ void For_RecForumPst (void)
{
case For_FORUM_GLOBAL_USRS:
case For_FORUM_SWAD_USRS:
Soc_StoreAndPublishSocialNote (Soc_NOTE_FORUM_POST,PstCod);
Soc_StoreAndPublishSocialNote (Soc_NOTE_FORUM_POST,PstCod,&SocPub);
break;
default:
break;

View File

@ -134,6 +134,7 @@ void Not_ReceiveNotice (void)
extern const char *Txt_Notice_created;
long NotCod;
unsigned NumUsrsToBeNotifiedByEMail;
struct SocialPublishing SocPub;
char Content[Cns_MAX_BYTES_TEXT+1];
/***** Get the text of the notice *****/
@ -155,7 +156,7 @@ void Not_ReceiveNotice (void)
Ntf_ShowAlertNumUsrsToBeNotifiedByEMail (NumUsrsToBeNotifiedByEMail);
/***** Create a new social note about the new notice *****/
Soc_StoreAndPublishSocialNote (Soc_NOTE_NOTICE,NotCod);
Soc_StoreAndPublishSocialNote (Soc_NOTE_NOTICE,NotCod,&SocPub);
}
/*****************************************************************************/

View File

@ -81,16 +81,6 @@ typedef enum
// when user clicks on link at bottom of timeline
} Soc_WhatToGetFromTimeline_t;
typedef enum
{
Soc_TOP_MESSAGE_NONE,
Soc_TOP_MESSAGE_SHARED,
Soc_TOP_MESSAGE_UNSHARED,
Soc_TOP_MESSAGE_FAV,
Soc_TOP_MESSAGE_UNFAV,
Soc_TOP_MESSAGE_COMMENTED,
} Soc_TopMessage_t;
static const Act_Action_t Soc_DefaultActions[Soc_NUM_NOTE_TYPES] =
{
ActUnk, // Soc_NOTE_UNKNOWN
@ -171,16 +161,6 @@ static const char *Soc_Icons[Soc_NUM_NOTE_TYPES] =
/****************************** Internal types *******************************/
/*****************************************************************************/
struct SocialPublishing
{
long PubCod;
long NotCod;
long PublisherCod; // Sharer or writer of a comment
Soc_PubType_t PubType;
time_t DateTimeUTC;
Soc_TopMessage_t TopMessage; // Used to show feedback on the action made
};
struct SocialNote
{
long NotCod;
@ -340,6 +320,8 @@ static void Soc_SetUniqueId (char UniqueId[Soc_MAX_LENGTH_ID]);
static void Soc_ClearTimelineThisSession (void);
static void Soc_AddNotesJustRetrievedToTimelineThisSession (void);
static void Str_AnalyzeTxtAndStoreNotifyEventToMentionedUsrs (long PubCod,const char *Txt);
/*****************************************************************************/
/***** Show social activity (timeline) including all the users I follow ******/
/*****************************************************************************/
@ -1251,7 +1233,6 @@ static void Soc_WriteSocialNote (const struct SocialNote *SocNot,
/* End of right part */
fprintf (Gbl.F.Out,"</div>");
fprintf (Gbl.F.Out,"<div class=\"SOCIAL_BOTTOM_LEFT\">");
/* Create unique id for new comment */
@ -1637,11 +1618,10 @@ static void Soc_GetNoteSummary (const struct SocialNote *SocNot,
/*****************************************************************************/
// Return the code of the new note just created
long Soc_StoreAndPublishSocialNote (Soc_NoteType_t NoteType,long Cod)
void Soc_StoreAndPublishSocialNote (Soc_NoteType_t NoteType,long Cod,struct SocialPublishing *SocPub)
{
char Query[256];
long HieCod; // Hierarchy code (institution/centre/degree/course)
struct SocialPublishing SocPub;
switch (NoteType)
{
@ -1673,14 +1653,12 @@ long Soc_StoreAndPublishSocialNote (Soc_NoteType_t NoteType,long Cod)
" (NoteType,UsrCod,HieCod,Cod,Unavailable,TimeNote)"
" VALUES ('%u','%ld','%ld','%ld','N',NOW())",
(unsigned) NoteType,Gbl.Usrs.Me.UsrDat.UsrCod,HieCod,Cod);
SocPub.NotCod = DB_QueryINSERTandReturnCode (Query,"can not create new social note");
SocPub->NotCod = DB_QueryINSERTandReturnCode (Query,"can not create new social note");
/***** Publish social note in timeline *****/
SocPub.PublisherCod = Gbl.Usrs.Me.UsrDat.UsrCod;
SocPub.PubType = Soc_PUB_ORIGINAL_NOTE;
Soc_PublishSocialNoteInTimeline (&SocPub);
return SocPub.NotCod;
SocPub->PublisherCod = Gbl.Usrs.Me.UsrDat.UsrCod;
SocPub->PubType = Soc_PUB_ORIGINAL_NOTE;
Soc_PublishSocialNoteInTimeline (SocPub);
}
/*****************************************************************************/
@ -1857,9 +1835,6 @@ static void Soc_PublishSocialNoteInTimeline (struct SocialPublishing *SocPub)
SocPub->PublisherCod,
(unsigned) SocPub->PubType);
SocPub->PubCod = DB_QueryINSERTandReturnCode (Query,"can not publish social note");
/***** Store notification about the new publishing *****/
Ntf_StoreNotifyEventsToAllUsrs (Ntf_EVENT_TIMELINE_PUBLISH,SocPub->PubCod);
}
/*****************************************************************************/
@ -2002,7 +1977,7 @@ static long Soc_ReceiveSocialPost (void)
char Content[Cns_MAX_BYTES_LONG_TEXT+1];
char Query[128+Cns_MAX_BYTES_LONG_TEXT];
long PstCod;
long NotCod;
struct SocialPublishing SocPub;
/***** Get the content of the new post *****/
Par_GetParAndChangeFormat ("Content",Content,Cns_MAX_BYTES_LONG_TEXT,
@ -2017,12 +1992,18 @@ static long Soc_ReceiveSocialPost (void)
PstCod = DB_QueryINSERTandReturnCode (Query,"can not create post");
/* Insert post in social notes */
NotCod = Soc_StoreAndPublishSocialNote (Soc_NOTE_SOCIAL_POST,PstCod);
Soc_StoreAndPublishSocialNote (Soc_NOTE_SOCIAL_POST,PstCod,&SocPub);
/***** Store notifications about the new publishing *****/
Ntf_StoreNotifyEventsToAllUsrs (Ntf_EVENT_TIMELINE_PUBLISH,SocPub.PubCod);
/***** Analyze content and store notifications about mentions *****/
Str_AnalyzeTxtAndStoreNotifyEventToMentionedUsrs (SocPub.PubCod,Content);
}
else
NotCod = -1L;
SocPub.NotCod = -1L;
return NotCod;
return SocPub.NotCod;
}
/*****************************************************************************/
@ -2731,9 +2712,15 @@ static long Soc_ReceiveComment (void)
Content);
DB_QueryINSERT (Query,"can not store comment content");
/***** Store notification about the new comment *****/
/***** Store notifications about the new publishing *****/
Ntf_StoreNotifyEventsToAllUsrs (Ntf_EVENT_TIMELINE_PUBLISH,SocPub.PubCod);
/***** Store notifications about the new comment *****/
Ntf_StoreNotifyEventsToAllUsrs (Ntf_EVENT_TIMELINE_COMMENT,SocPub.PubCod);
/***** Analyze content and store notifications about mentions *****/
Str_AnalyzeTxtAndStoreNotifyEventToMentionedUsrs (SocPub.PubCod,Content);
/***** Show the social note just commented *****/
Soc_WriteSocialNote (&SocNot,
Soc_TOP_MESSAGE_COMMENTED,Gbl.Usrs.Me.UsrDat.UsrCod,
@ -2811,6 +2798,9 @@ static long Soc_ShareSocialNote (void)
/* Update number of times this social note is shared */
SocNot.NumShared = Soc_UpdateNumTimesANoteHasBeenShared (&SocNot);
/***** Store notifications about the new publishing *****/
Ntf_StoreNotifyEventsToAllUsrs (Ntf_EVENT_TIMELINE_PUBLISH,SocPub.PubCod);
}
}
else
@ -4438,3 +4428,89 @@ void Soc_GetNotifSocialPublishing (char *SummaryStr,char **ContentStr,long PubCo
if ((*ContentStr = (char *) malloc (strlen (Content)+1)) != NULL)
strcpy (*ContentStr,Content);
}
/*****************************************************************************/
/*** Create a notification about mention for any nickname in a publishing ****/
/*****************************************************************************/
/*
Example: "The user @rms says..."
^ ^
PtrStart ___| |___ PtrEnd
Length = 3
*/
static void Str_AnalyzeTxtAndStoreNotifyEventToMentionedUsrs (long PubCod,const char *Txt)
{
const char *Ptr;
bool IsNickname;
struct
{
const char *PtrStart;
const char *PtrEnd;
size_t Length; // Length of the nickname
} Nickname;
struct UsrData UsrDat;
bool CreateNotif;
bool NotifyByEmail;
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
/***** Find nicknames and create notifications *****/
for (Ptr = Txt;
*Ptr;)
/* Check if the next char is the start of a nickname */
if ((int) *Ptr == (int) '@')
{
/* Find nickname end */
Ptr++; // Points to first character after @
Nickname.PtrStart = Ptr;
/* A nick can have digits, letters and '_' */
for (;
*Ptr;
Ptr++)
if (!((*Ptr >= 'a' && *Ptr <= 'z') ||
(*Ptr >= 'A' && *Ptr <= 'Z') ||
(*Ptr >= '0' && *Ptr <= '9') ||
(*Ptr == '_')))
break;
/* Calculate length of this nickname */
Nickname.PtrEnd = Ptr - 1;
Nickname.Length = (size_t) (Ptr - Nickname.PtrStart);
/* A nick (without arroba) must have a number of characters
Nck_MIN_LENGTH_NICKNAME_WITHOUT_ARROBA <= Length <= Nck_MAX_LENGTH_NICKNAME_WITHOUT_ARROBA */
IsNickname = (Nickname.Length >= Nck_MIN_LENGTH_NICKNAME_WITHOUT_ARROBA &&
Nickname.Length <= Nck_MAX_LENGTH_NICKNAME_WITHOUT_ARROBA);
if (IsNickname)
{
/* Copy nickname */
strncpy (UsrDat.Nickname,Nickname.PtrStart,Nickname.Length);
UsrDat.Nickname[Nickname.Length] = '\0';
if ((UsrDat.UsrCod = Nck_GetUsrCodFromNickname (UsrDat.Nickname)) > 0)
if (UsrDat.UsrCod != Gbl.Usrs.Me.UsrDat.UsrCod) // It's not me
{
/* Get user's data */
Usr_GetAllUsrDataFromUsrCod (&UsrDat);
/* Create notification for the mentioned user *****/
CreateNotif = (UsrDat.Prefs.NotifNtfEvents & (1 << Ntf_EVENT_TIMELINE_MENTION));
if (CreateNotif)
{
NotifyByEmail = (UsrDat.Prefs.EmailNtfEvents & (1 << Ntf_EVENT_TIMELINE_MENTION));
Ntf_StoreNotifyEventToOneUser (Ntf_EVENT_TIMELINE_MENTION,&UsrDat,PubCod,
(Ntf_Status_t) (NotifyByEmail ? Ntf_STATUS_BIT_EMAIL :
0));
}
}
}
}
/* The next char is not the start of a nickname */
else // Character != '@'
Ptr++;
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
}

View File

@ -87,6 +87,26 @@ typedef enum
} Soc_NoteType_t;
typedef enum
{
Soc_TOP_MESSAGE_NONE,
Soc_TOP_MESSAGE_SHARED,
Soc_TOP_MESSAGE_UNSHARED,
Soc_TOP_MESSAGE_FAV,
Soc_TOP_MESSAGE_UNFAV,
Soc_TOP_MESSAGE_COMMENTED,
} Soc_TopMessage_t;
struct SocialPublishing
{
long PubCod;
long NotCod;
long PublisherCod; // Sharer or writer of a comment
Soc_PubType_t PubType;
time_t DateTimeUTC;
Soc_TopMessage_t TopMessage; // Used to show feedback on the action made
};
/*****************************************************************************/
/****************************** Public prototypes ****************************/
/*****************************************************************************/
@ -99,7 +119,7 @@ void Soc_RefreshNewTimelineGbl (void);
void Soc_RefreshOldTimelineGbl (void);
void Soc_RefreshOldTimelineUsr (void);
long Soc_StoreAndPublishSocialNote (Soc_NoteType_t NoteType,long Cod);
void Soc_StoreAndPublishSocialNote (Soc_NoteType_t NoteType,long Cod,struct SocialPublishing *SocPub);
void Soc_MarkSocialNoteAsUnavailableUsingNotCod (long NotCod);
void Soc_MarkSocialNoteAsUnavailableUsingNoteTypeAndCod (Soc_NoteType_t NoteType,long Cod);
void Soc_MarkSocialNoteOneFileAsUnavailable (const char *Path);

View File

@ -213,7 +213,7 @@ void Str_InsertLinks (char *Txt,unsigned long MaxLength,size_t MaxCharsURLOnScre
}
/* Calculate length of this URL */
Links[NumLinks].NumActualBytes = (size_t) (Links[NumLinks].PtrEnd - Links[NumLinks].PtrStart) + 1;
Links[NumLinks].NumActualBytes = (size_t) (Links[NumLinks].PtrEnd + 1 - Links[NumLinks].PtrStart);
if (Links[NumLinks].NumActualBytes <= MaxCharsURLOnScreen)
LinksTotalLength += Links[NumLinks].NumActualBytes;
else // If URL is too long to be displayed ==> short it
@ -260,7 +260,7 @@ void Str_InsertLinks (char *Txt,unsigned long MaxLength,size_t MaxCharsURLOnScre
/* Calculate length of this nickname */
Links[NumLinks].PtrEnd = PtrSrc - 1;
Links[NumLinks].NumActualBytes = (size_t) (Links[NumLinks].PtrEnd - Links[NumLinks].PtrStart) + 1;
Links[NumLinks].NumActualBytes = (size_t) (PtrSrc - Links[NumLinks].PtrStart);
/* A nick (without arroba) must have a number of characters
Nck_MIN_LENGTH_NICKNAME_WITHOUT_ARROBA <= Length <= Nck_MAX_LENGTH_NICKNAME_WITHOUT_ARROBA */
@ -285,7 +285,7 @@ void Str_InsertLinks (char *Txt,unsigned long MaxLength,size_t MaxCharsURLOnScre
}
}
/* The next char is not the start of URL or nickname */
else // Character != 'h'
else // Character distinct to 'h' or '@'
PtrSrc++;
/***** If there are one or more links (URLs or nicknames) in text *****/