diff --git a/css/swad16.135.css b/css/swad16.136.css similarity index 99% rename from css/swad16.135.css rename to css/swad16.136.css index a8baab73c..614b4096a 100644 --- a/css/swad16.135.css +++ b/css/swad16.136.css @@ -1074,6 +1074,11 @@ a:hover /* Default ==> underlined */ white-space:nowrap; overflow:hidden; } +.CONNECTED_TXT + { + color:#398000; + font-size:12pt; + } /*************************** Most frequent actions ***************************/ #MFU_actions @@ -1712,11 +1717,6 @@ a:hover img.CENTRE_PHOTO_SHOW .BLUE_USR {color:white; font-size:15pt; font-weight:bold; white-space:nowrap;} .YELLOW_USR {color:#B3B0B3; font-size:15pt; font-weight:bold; white-space:nowrap;} -.WHITE_CONNECTED {color:#398000; font-size:12pt;} -.GREY_CONNECTED {color:#398000; font-size:12pt;} -.BLUE_CONNECTED {color:#398000; font-size:12pt;} -.YELLOW_CONNECTED {color:#398000; font-size:12pt;} - .WHITE_TITLE {color:#505050; font-size:18pt;} .GREY_TITLE {color:#505050; font-size:18pt;} .BLUE_TITLE {color:#4D88A1; font-size:18pt;} diff --git a/swad_changelog.h b/swad_changelog.h index f0097749d..0a9704993 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -192,21 +192,21 @@ // TODO: En los detalles de asistencia debería salir la fecha de cada sesión // TODO: System admin should view link "Visits to course" -// TODO: En "A quien seguir" poner el país de cada usuario. -// TODO: Sugerir un usuario al que seguir debajo del banner de la derecha, para aumentar número de seguidores. +// TODO: Bajo la foto de cada usuario el país // TODO: Permitir elegir entre "Ver actividad de quienes sigo" o "Ver actividad de todos" /*****************************************************************************/ /****************************** Public constants *****************************/ /*****************************************************************************/ -#define Log_PLATFORM_VERSION "SWAD 16.135.7 (2017-02-16)" -#define CSS_FILE "swad16.135.css" +#define Log_PLATFORM_VERSION "SWAD 16.136 (2017-02-16)" +#define CSS_FILE "swad16.136.css" #define JS_FILE "swad16.123.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 16.136: Feb 16, 2017 Sggested users to follow on right column. (212646 lines) Version 16.135.7: Feb 16, 2017 Code refactoring in users to follow. (212512 lines) Version 16.135.6: Feb 13, 2017 Changes in contextual help after changes in tabs. (212501 lines) Version 16.135.5: Feb 11, 2017 Change in button to register teacher when no teachers found. diff --git a/swad_connected.c b/swad_connected.c index 2901c322c..0db4fad16 100644 --- a/swad_connected.c +++ b/swad_connected.c @@ -342,7 +342,6 @@ void Con_GetAndShowLastClicks (void) void Con_ShowGlobalConnectedUsrs (void) { - extern const char *The_ClassConnected[The_NUM_THEMES]; extern const char *Txt_Connected_users; extern const char *Txt_session; extern const char *Txt_sessions; @@ -369,7 +368,7 @@ void Con_ShowGlobalConnectedUsrs (void) Act_FormStartUnique (ActLstCon); // Must be unique because // the list of connected users // is dynamically updated via AJAX - Act_LinkFormSubmitUnique (Txt_Connected_users,The_ClassConnected[Gbl.Prefs.Theme]); + Act_LinkFormSubmitUnique (Txt_Connected_users,"CONNECTED_TXT"); /* Write total number of sessions */ fprintf (Gbl.F.Out,"%u %s", @@ -458,7 +457,6 @@ static void Con_ComputeConnectedUsrsWithARoleBelongingToCurrentCrs (Rol_Role_t R static void Con_ShowConnectedUsrsBelongingToLocation (void) { - extern const char *The_ClassConnected[The_NUM_THEMES]; extern const char *Txt_from; char LocationName[Hie_MAX_LENGTH_LOCATION_SHORT_NAME_SPEC_CHAR + 1]; struct ConnectedUsrs Usrs; @@ -515,8 +513,7 @@ static void Con_ShowConnectedUsrsBelongingToLocation (void) /***** Number of connected users who belong to scope *****/ Con_GetNumConnectedUsrsWithARoleBelongingCurrentLocation (Rol_UNKNOWN,&Usrs); - fprintf (Gbl.F.Out,"
%u %s ", - The_ClassConnected[Gbl.Prefs.Theme], + fprintf (Gbl.F.Out,"
%u %s ", Usrs.NumUsrs, Txt_from); if (Gbl.Usrs.Me.LoggedRole >= Rol_DEG_ADM) @@ -552,7 +549,6 @@ static void Con_ShowConnectedUsrsBelongingToLocation (void) void Con_ShowConnectedUsrsBelongingToCurrentCrs (void) { - extern const char *The_ClassConnected[The_NUM_THEMES]; extern const char *Txt_Connected_users; extern const char *Txt_from; char CourseName[Crs_MAX_LENGTH_COURSE_SHRT_NAME + 1]; @@ -569,7 +565,7 @@ void Con_ShowConnectedUsrsBelongingToCurrentCrs (void) Act_FormStartUnique (ActLstCon); // Must be unique because // the list of connected users // is dynamically updated via AJAX - Act_LinkFormSubmitUnique (Txt_Connected_users,The_ClassConnected[Gbl.Prefs.Theme]); + Act_LinkFormSubmitUnique (Txt_Connected_users,"CONNECTED_TXT"); /* Write total number of connected users belonging to the current course */ Str_Copy (CourseName,Gbl.CurrentCrs.Crs.ShrtName, @@ -659,7 +655,6 @@ static void Con_ShowConnectedUsrsWithARoleBelongingToCurrentLocationOnMainZone ( static void Con_ShowConnectedUsrsWithARoleBelongingToCurrentCrsOnRightColumn (Rol_Role_t Role) { - extern const char *The_ClassConnected[The_NUM_THEMES]; extern const char *Txt_ROLES_SINGUL_abc[Rol_NUM_ROLES][Usr_NUM_SEXS]; extern const char *Txt_ROLES_PLURAL_abc[Rol_NUM_ROLES][Usr_NUM_SEXS]; extern const char *Txt_Connected_users; @@ -695,7 +690,7 @@ static void Con_ShowConnectedUsrsWithARoleBelongingToCurrentCrsOnRightColumn (Ro // the list of connected users // is dynamically updated via AJAX Sco_PutParamScope ("ScopeCon",Sco_SCOPE_CRS); - Act_LinkFormSubmitUnique (Txt_Connected_users,The_ClassConnected[Gbl.Prefs.Theme]); + Act_LinkFormSubmitUnique (Txt_Connected_users,"CONNECTED_TXT"); fprintf (Gbl.F.Out,"\"%s\"" "", diff --git a/swad_follow.c b/swad_follow.c index d6946cd52..c9fca56ce 100644 --- a/swad_follow.c +++ b/swad_follow.c @@ -47,8 +47,6 @@ #define Fol_NUM_COLUMNS_FOLLOW 3 -#define Fol_MAX_USRS_TO_FOLLOW_SUGGESTED (Fol_NUM_COLUMNS_FOLLOW * 3) - /*****************************************************************************/ /****************************** Internal types *******************************/ /*****************************************************************************/ @@ -67,7 +65,8 @@ extern struct Globals Gbl; /***************************** Private prototypes ****************************/ /*****************************************************************************/ -static unsigned Fol_GetUsrsWhoToFollow (MYSQL_RES **mysql_res); +static unsigned Fol_GetUsrsWhoToFollow (unsigned MaxUsrsToShow, + MYSQL_RES **mysql_res); static void Fol_PutIconsWhoToFollow (void); static void Fol_PutIconToUpdateWhoToFollow (void); @@ -81,6 +80,10 @@ static void Fol_ListFollowingUsr (struct UsrData *UsrDat); static void Fol_ListFollowersUsr (struct UsrData *UsrDat); static void Fol_ShowFollowedOrFollower (struct UsrData *UsrDat); +static void Fol_WriteRowUsrToFollowOnRightColumn (struct UsrData *UsrDat); +static void Fol_PutInactiveIconToFollowUnfollow (void); +static void Fol_PutIconToFollow (struct UsrData *UsrDat); +static void Fol_PutIconToUnfollow (struct UsrData *UsrDat); /*****************************************************************************/ /********************** Put link to show users to follow **********************/ @@ -99,10 +102,12 @@ void Fol_PutLinkWhoToFollow (void) } /*****************************************************************************/ -/***************************** Show users to follow **************************/ +/****************** Show several users to follow on main zone ****************/ /*****************************************************************************/ -void Fol_SuggestWhoToFollow (void) +#define Fol_MAX_USRS_TO_FOLLOW_MAIN_ZONE (Fol_NUM_COLUMNS_FOLLOW * 3) + +void Fol_SuggestUsrsToFollowMainZone (void) { extern const char *Hlp_SOCIAL_Profiles_who_to_follow; extern const char *Txt_Who_to_follow; @@ -117,7 +122,8 @@ void Fol_SuggestWhoToFollow (void) Prf_PutLinkRequestUserProfile (); /***** Get users *****/ - if ((NumUsrs = Fol_GetUsrsWhoToFollow (&mysql_res))) + if ((NumUsrs = Fol_GetUsrsWhoToFollow (Fol_MAX_USRS_TO_FOLLOW_MAIN_ZONE, + &mysql_res))) { /***** Start frame *****/ Lay_StartRoundFrameTable ("560px",Txt_Who_to_follow, @@ -161,11 +167,77 @@ void Fol_SuggestWhoToFollow (void) DB_FreeMySQLResult (&mysql_res); } +/*****************************************************************************/ +/**************** Show several users to follow on right column ***************/ +/*****************************************************************************/ + +#define Fol_MAX_USRS_TO_FOLLOW_RIGHT_COLUMN 3 + +void Fol_SuggestUsrsToFollowMainZoneOnRightColumn (void) + { + extern const char *Txt_Who_to_follow; + extern const char *Txt_No_user_to_whom_you_can_follow_Try_again_later; + MYSQL_RES *mysql_res; + MYSQL_ROW row; + unsigned NumUsrs; + unsigned NumUsr; + struct UsrData UsrDat; + + /***** Get users *****/ + if ((NumUsrs = Fol_GetUsrsWhoToFollow (Fol_MAX_USRS_TO_FOLLOW_RIGHT_COLUMN, + &mysql_res))) + { + /***** Start container *****/ + fprintf (Gbl.F.Out,"
"); + + /***** Title with link to suggest more users to follow *****/ + Act_FormStart (ActSeeSocPrf); + Act_LinkFormSubmit (Txt_Who_to_follow,"CONNECTED_TXT",NULL); + fprintf (Gbl.F.Out,"%s",Txt_Who_to_follow); + Act_FormEnd (); + + /***** Start table *****/ + fprintf (Gbl.F.Out,""); + + /***** Initialize structure with user's data *****/ + Usr_UsrDataConstructor (&UsrDat); + + /***** List users *****/ + for (NumUsr = 0; + NumUsr < NumUsrs; + NumUsr++) + { + /***** Get user *****/ + row = mysql_fetch_row (mysql_res); + + /* Get user's code (row[0]) */ + UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]); + + /***** Show user *****/ + if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat)) + Fol_WriteRowUsrToFollowOnRightColumn (&UsrDat); + } + + /***** Free memory used for user's data *****/ + Usr_UsrDataDestructor (&UsrDat); + + /***** End table *****/ + fprintf (Gbl.F.Out,"
"); + + /***** End container *****/ + fprintf (Gbl.F.Out,"
"); + } + + /***** Free structure that stores the query result *****/ + DB_FreeMySQLResult (&mysql_res); + } + /*****************************************************************************/ /*************************** Get users to follow *****************************/ /*****************************************************************************/ -static unsigned Fol_GetUsrsWhoToFollow (MYSQL_RES **mysql_res) +static unsigned Fol_GetUsrsWhoToFollow (unsigned MaxUsrsToShow, + MYSQL_RES **mysql_res) { extern const char *Pri_VisibilityDB[Pri_NUM_OPTIONS_PRIVACY]; char Query[2048]; @@ -230,7 +302,7 @@ static unsigned Fol_GetUsrsWhoToFollow (MYSQL_RES **mysql_res) " WHERE UsrCod NOT IN" " (SELECT FollowedCod FROM usr_follow" " WHERE FollowerCod='%ld')" - // Get only Fol_MAX_USRS_TO_FOLLOW_SUGGESTED * 2 users + // Get only MaxUsrsToShow * 2 users " ORDER BY RAND() LIMIT %u" ")" " UNION " @@ -247,12 +319,13 @@ static unsigned Fol_GetUsrsWhoToFollow (MYSQL_RES **mysql_res) " AND UsrCod NOT IN" " (SELECT FollowedCod FROM usr_follow" " WHERE FollowerCod='%ld')" - // Get only Fol_MAX_USRS_TO_FOLLOW_SUGGESTED users + // Get only MaxUsrsToShow users " ORDER BY RAND() LIMIT %u" ")" ") AS UsrsToFollow" - // Get only Fol_MAX_USRS_TO_FOLLOW_SUGGESTED users + // Get only MaxUsrsToShow users " ORDER BY RAND() LIMIT %u", + Gbl.Usrs.Me.UsrDat.UsrCod, Gbl.Usrs.Me.UsrDat.UsrCod, Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM], @@ -265,15 +338,15 @@ static unsigned Fol_GetUsrsWhoToFollow (MYSQL_RES **mysql_res) Gbl.Usrs.Me.UsrDat.UsrCod, Pri_VisibilityDB[Pri_VISIBILITY_USER ], Gbl.Usrs.Me.UsrDat.UsrCod, - Fol_MAX_USRS_TO_FOLLOW_SUGGESTED * 2, // 2/3 likely known users + MaxUsrsToShow * 2, // 2/3 likely known users Gbl.Usrs.Me.UsrDat.UsrCod, Pri_VisibilityDB[Pri_VISIBILITY_SYSTEM], Pri_VisibilityDB[Pri_VISIBILITY_WORLD ], Gbl.Usrs.Me.UsrDat.UsrCod, - Fol_MAX_USRS_TO_FOLLOW_SUGGESTED, // 1/3 likely unknown users + MaxUsrsToShow, // 1/3 likely unknown users - Fol_MAX_USRS_TO_FOLLOW_SUGGESTED); + MaxUsrsToShow); return DB_QuerySELECT (Query,mysql_res,"can not get users to follow"); } @@ -690,9 +763,6 @@ static void Fol_ListFollowersUsr (struct UsrData *UsrDat) static void Fol_ShowFollowedOrFollower (struct UsrData *UsrDat) { extern const char *Txt_View_public_profile; - extern const char *Txt_Following_unfollow; - extern const char *Txt_Unfollow; - extern const char *Txt_Follow; bool ShowPhoto; char PhotoURL[PATH_MAX + 1]; bool Visible = Pri_ShowingIsAllowed (UsrDat->ProfileVisibility,UsrDat); @@ -724,51 +794,146 @@ static void Fol_ShowFollowedOrFollower (struct UsrData *UsrDat) if (!Gbl.Usrs.Me.Logged || // Not logged Gbl.Usrs.Me.UsrDat.UsrCod == UsrDat->UsrCod) // It's me /* Inactive icon to follow/unfollow */ - fprintf (Gbl.F.Out,"
" - "\"\""" - "
", - Gbl.Prefs.IconsURL); + Fol_PutInactiveIconToFollowUnfollow (); else { /* Put form to follow / unfollow */ if (Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,UsrDat->UsrCod)) // I follow user - { /* Form to unfollow */ - Act_FormStart (ActUnfUsr); - Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod); - Act_LinkFormSubmit (Txt_Following_unfollow,NULL,NULL); - fprintf (Gbl.F.Out,"
" - "\"%s\"" - "
" - "", - Gbl.Prefs.IconsURL, - Txt_Unfollow,Txt_Following_unfollow); - Act_FormEnd (); - } + Fol_PutIconToUnfollow (UsrDat); else if (Visible) // I do not follow this user and I can follow - { /* Form to follow */ - Act_FormStart (ActFolUsr); - Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod); - Act_LinkFormSubmit (Txt_Follow,NULL,NULL); - fprintf (Gbl.F.Out,"
" - "\"%s\"" - "
" - "", - Gbl.Prefs.IconsURL, - Txt_Follow,Txt_Follow); - Act_FormEnd (); - } + Fol_PutIconToFollow (UsrDat); } fprintf (Gbl.F.Out,""); } +/*****************************************************************************/ +/********************* Write the name of a connected user ********************/ +/*****************************************************************************/ + +static void Fol_WriteRowUsrToFollowOnRightColumn (struct UsrData *UsrDat) + { + extern const char *Txt_View_public_profile; + bool ShowPhoto; + char PhotoURL[PATH_MAX + 1]; + bool Visible = Pri_ShowingIsAllowed (UsrDat->ProfileVisibility,UsrDat); + + /***** Show user's photo *****/ + fprintf (Gbl.F.Out,"" + "", + Gbl.RowEvenOdd); + if (Visible) + { + ShowPhoto = Pho_ShowingUsrPhotoIsAllowed (UsrDat,PhotoURL); + Pho_ShowUsrPhoto (UsrDat,ShowPhoto ? PhotoURL : + NULL, + "PHOTO21x28",Pho_ZOOM,false); + } + fprintf (Gbl.F.Out,""); + + /***** User's name *****/ + fprintf (Gbl.F.Out,"", + Gbl.RowEvenOdd); + if (Visible) + { + /* Put form to go to public profile */ + Act_FormStart (ActSeePubPrf); + Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod); + Act_LinkFormSubmit (Txt_View_public_profile,"CON_CRS",NULL); + Usr_RestrictLengthAndWriteName (UsrDat,10); + fprintf (Gbl.F.Out,""); + Act_FormEnd (); + } + fprintf (Gbl.F.Out,""); + + /***** Icon to follow *****/ + fprintf (Gbl.F.Out,"", + Gbl.RowEvenOdd); + if (!Gbl.Usrs.Me.Logged || // Not logged + Gbl.Usrs.Me.UsrDat.UsrCod == UsrDat->UsrCod) // It's me + /* Inactive icon to follow/unfollow */ + Fol_PutInactiveIconToFollowUnfollow (); + else + { + /* Put form to follow / unfollow */ + if (Fol_CheckUsrIsFollowerOf (Gbl.Usrs.Me.UsrDat.UsrCod,UsrDat->UsrCod)) // I follow user + /* Form to unfollow */ + Fol_PutIconToUnfollow (UsrDat); + else if (Visible) // I do not follow this user and I can follow + /* Form to follow */ + Fol_PutIconToFollow (UsrDat); + } + fprintf (Gbl.F.Out,"" + ""); + + Gbl.RowEvenOdd = 1 - Gbl.RowEvenOdd; + } + +/*****************************************************************************/ +/*********************** Put icon to unfollow another user *********************/ +/*****************************************************************************/ + +static void Fol_PutInactiveIconToFollowUnfollow (void) + { + /***** Inactive icon to follow/unfollow *****/ + fprintf (Gbl.F.Out,"
" + "\"\""" + "
", + Gbl.Prefs.IconsURL); + } + +/*****************************************************************************/ +/*********************** Put icon to unfollow another user *********************/ +/*****************************************************************************/ + +static void Fol_PutIconToFollow (struct UsrData *UsrDat) + { + extern const char *Txt_Follow; + + /***** Form to unfollow *****/ + Act_FormStart (ActFolUsr); + Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod); + Act_LinkFormSubmit (Txt_Follow,NULL,NULL); + fprintf (Gbl.F.Out,"
" + "\"%s\"" + "
" + "", + Gbl.Prefs.IconsURL, + Txt_Follow,Txt_Follow); + Act_FormEnd (); + } + +/*****************************************************************************/ +/********************** Put icon to unfollow another user ********************/ +/*****************************************************************************/ + +static void Fol_PutIconToUnfollow (struct UsrData *UsrDat) + { + extern const char *Txt_Unfollow; + + /* Form to follow */ + Act_FormStart (ActFolUsr); + Usr_PutParamUsrCodEncrypted (UsrDat->EncryptedUsrCod); + Act_LinkFormSubmit (Txt_Unfollow,NULL,NULL); + fprintf (Gbl.F.Out,"
" + "\"%s\"" + "
" + "", + Gbl.Prefs.IconsURL, + Txt_Unfollow,Txt_Unfollow); + Act_FormEnd (); + } + /*****************************************************************************/ /***************************** Follow another user ***************************/ /*****************************************************************************/ diff --git a/swad_follow.h b/swad_follow.h index 6b57710f2..5b47a1910 100644 --- a/swad_follow.h +++ b/swad_follow.h @@ -44,7 +44,8 @@ /*****************************************************************************/ void Fol_PutLinkWhoToFollow (void); -void Fol_SuggestWhoToFollow (void); +void Fol_SuggestUsrsToFollowMainZone (void); +void Fol_SuggestUsrsToFollowMainZoneOnRightColumn (void); bool Fol_CheckUsrIsFollowerOf (long FollowerCod,long FollowedCod); unsigned Fol_GetNumFollowing (long UsrCod); diff --git a/swad_layout.c b/swad_layout.c index 2010c4a08..683eeb532 100644 --- a/swad_layout.c +++ b/swad_layout.c @@ -36,6 +36,7 @@ #include "swad_connected.h" #include "swad_database.h" #include "swad_exam.h" +#include "swad_follow.h" #include "swad_global.h" #include "swad_hierarchy.h" #include "swad_logo.h" @@ -1016,6 +1017,13 @@ static void Lay_ShowRightColumn (void) Con_ShowConnectedUsrsBelongingToCurrentCrs (); fprintf (Gbl.F.Out,"
"); // Used for AJAX based refresh } + else + { + /***** Suggest one user to follow *****/ + fprintf (Gbl.F.Out,"
"); + Fol_SuggestUsrsToFollowMainZoneOnRightColumn (); + fprintf (Gbl.F.Out,"
"); + } /***** SWADroid advertisement *****/ if (!Gbl.Usrs.Me.Logged || diff --git a/swad_profile.c b/swad_profile.c index 01bfb71bc..2923b88aa 100644 --- a/swad_profile.c +++ b/swad_profile.c @@ -101,7 +101,7 @@ static void Prf_GetAndShowRankingFigure (const char *FieldName); void Prf_SeeSocialProfiles (void) { if (Gbl.Usrs.Me.Logged) - Fol_SuggestWhoToFollow (); + Fol_SuggestUsrsToFollowMainZone (); else Prf_RequestUserProfile (); } diff --git a/swad_theme.c b/swad_theme.c index 1fb12ce64..6efd21b99 100644 --- a/swad_theme.c +++ b/swad_theme.c @@ -135,14 +135,6 @@ const char *The_ClassCourse[The_NUM_THEMES] = "YELLOW_COURSE", }; -const char *The_ClassConnected[The_NUM_THEMES] = - { - "WHITE_CONNECTED", - "GREY_CONNECTED", - "BLUE_CONNECTED", - "YELLOW_CONNECTED", - }; - const char *The_ClassTxtMenuOff[The_NUM_THEMES] = { "WHITE_MENU_OFF",