Welcome Guest! To enable all features please Login or Register.
Options
View
Go to last post Go to first unread
Offline tommy382  
#1 Posted : Saturday, March 12, 2011 1:39:15 AM(UTC)
tommy382


Rank: YAF Commander

Reputation:

Joined: 4/11/2008(UTC)
Posts: 94

Thanks: 10 times
Was thanked: 3 time(s) in 3 post(s)
I added more statistical data to the forum. These data are the visitors count in the last 24 hours and the visitor count in the last 30 days. These are important short term and long term trends for the site admin to have. I also listed the visitors that visited in the last 24 hours as shown below.
UserPostedImage

I would like to use Styled Nick. I can get the data from the DB but would like to use existing code to promote reusability so I added the following code that is basically like the "active users" but I used the length of one day instead of the minutes from the Board Settings.
Code:
      //Tommy
      {
        DataTable activeUsersOneDay = this.Get<IDataCache>().GetOrSet(
          "VisitorsInTheLast24Hours",
          () => this.Get<IDBBroker>().GetActiveList(60 * 24, false, false),
          TimeSpan.FromMilliseconds(this.Get<YafBoardSettings>().OnlineStatusCacheTimeout));
        this.activeUsersOneDay.ActiveUserTable = activeUsersOneDay;
      }


However, this code caused the control ID conflict error below. Shouldn't the "ActiveUsers" control be able to have multiple instances? What change can I make to allow that control to be able to have multiple instances in the same page?

thanks 1 user thanked tommy382 for this useful post.
Zero2Cool on 9/10/2011(UTC)
Sponsor
Offline tommy382  
#2 Posted : Saturday, March 12, 2011 5:26:10 AM(UTC)
tommy382


Rank: YAF Commander

Reputation:

Joined: 4/11/2008(UTC)
Posts: 94

Thanks: 10 times
Was thanked: 3 time(s) in 3 post(s)
I got it working. The styled nicks look good and they are linkable too.
UserPostedImage


Here are my changes in case someone want to incorporate this into YAF. I just use English but one might want to define the messages in other languages and use localization XML for non-English users.


ActiveUsers.cs - This fixes the control ID conflict noted above:
Code:

          if (!isCrawler)
          {
              userLink.ID = "UserLink" + this.InstantId + userLink.UserID;
          }
          else
          {
            userLink.ID += userLink.ReplaceName;
          }


ForumStatistics.ascx.cs:
Code:
    private void ForumStatistics_Load([NotNull] object sender, [NotNull] EventArgs e)
    {
...

      // "Active Users" Count and Most Users Count
      DataRow activeStats = LegacyDb.active_stats(this.PageContext.PageBoardID);
      this.ActiveUserCount.Text = this.FormatActiveUsers(activeStats);

      //Tommy
      {
        DataTable activeUsers1Day = this.Get<IDataCache>().GetOrSet(
          "VisitorsInTheLast24Hours",
          () => this.Get<IDBBroker>().GetRecentUsers(60 * 24),
          TimeSpan.FromMinutes(this.Get<YafBoardSettings>().ForumStatisticsCacheTimeout));
        this.activeUsersOneDay.ActiveUserTable = activeUsers1Day;

        DataTable activeUsers30Day = this.Get<IDataCache>().GetOrSet(
          "VisitorsInTheLast30Days",
          () => this.Get<IDBBroker>().GetRecentUsers(60 * 24 * 30),
          TimeSpan.FromMinutes(this.Get<YafBoardSettings>().ForumStatisticsCacheTimeout));

        ltrRecentUsers.Text =
          string.Format("Members online within the last 24 hours is {0}, within the last 30 days is {1}.",
          activeUsers1Day.Rows.Count,
          activeUsers30Day.Rows.Count);
      }


IDBBroker.cs:
Code:
    /// <summary>
    /// Get the list of recently logged in users.
    /// </summary>
    /// <param name="timeSinceLastLogin">Time since last login in minutes.</param>
    /// <returns>The DataTable of the users.</returns>
    DataTable GetRecentUsers(int timeSinceLastLogin);


YafDBBroker.cs:
Code:
    /// <summary>
    /// Get the list of recently logged in users.
    /// </summary>
    /// <param name="timeSinceLastLogin">The time since last login in minutes.</param>
    /// <returns>The list of users in Datatable format.</returns>
    public DataTable GetRecentUsers(int timeSinceLastLogin)
    {
      return
        this.StyleTransformDataTable(
          LegacyDb.recent_users(
            YafContext.Current.PageBoardID, timeSinceLastLogin,
            this.Get<YAF.Classes.YafBoardSettings>().UseStyledNicks));
    }


LegacyDb.cs:
Code:
    public static DataTable recent_users(object boardID, int timeSinceLastLogin, object styledNicks)
    {
      using (var cmd = MsSqlDbAccess.GetCommand("recent_users"))
      {
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.AddWithValue("BoardID", boardID);
        cmd.Parameters.AddWithValue("TimeSinceLastLogin", timeSinceLastLogin);
        cmd.Parameters.AddWithValue("StyledNicks", styledNicks);
        return MsSqlDbAccess.Current.GetData(cmd);
      }
    }


New DB Stored Procedure:
Code:
USE [YafForum]
GO
/****** Object:  StoredProcedure [dbo].[yaf_recent_users]    Script Date: 03/12/2011 03:45:32 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER procedure [dbo].[yaf_recent_users](@BoardID int,@TimeSinceLastLogin int,@StyledNicks bit=0) as
begin	
	SELECT U.UserId,
	IsCrawler = 0,
	UserCount = 1,
	IsHidden = (IsActiveExcluded),
	Style = CASE(@StyledNicks)
				WHEN 1 THEN
						ISNULL ((SELECT TOP 1 G.Style
						 FROM [dbo].[yaf_UserGroup] AS UG
							  JOIN [dbo].[yaf_Group] G on G.GroupID=UG.GroupID
							  WHERE UG.UserID=U.UserID AND LEN(G.Style) > 2 
							  ORDER BY G.SortOrder), '')
				ELSE ''
			END
	FROM [dbo].[yaf_User] AS U
				JOIN [dbo].[yaf_Rank] R on R.RankID=U.RankID
	WHERE (U.IsApproved = '1') AND
	 U.BoardID = @BoardID AND
	 (DATEADD(mi, 0 - @TimeSinceLastLogin, GETDATE()) < U.LastVisit) AND
				--Excluding guests
				NOT EXISTS(				
					SELECT 1 
						FROM [dbo].[yaf_UserGroup] x
							inner join [dbo].[yaf_Group] y ON y.GroupID=x.GroupID 
						WHERE x.UserID=U.UserID and (y.Flags & 2)<>0
					)
	ORDER BY U.LastVisit
end

Edited by user Wednesday, March 16, 2011 3:46:20 AM(UTC)  | Reason: Not specified

Offline bbobb  
#3 Posted : Saturday, March 12, 2011 6:57:53 AM(UTC)
bbobb


Rank: YAF Developer

Reputation:

Medals: Medal of Honor Key: Given to pillars of the community who are key players in the YAF community and project.Medal of Honor for a YAF Database Key Player: Holds the key to YAF database. Bow down!Medal of Honor for the Support King: Given for answering tons of support questions and generally helping the community.Medal of Honor for the Support Knight: Given to a community member who has answered lots of support questions.

Joined: 10/21/2008(UTC)
Posts: 1,543

Thanks: 46 times
Was thanked: 281 time(s) in 248 post(s)
tommy382 Offline ThumpUp .Just a notion -you use OnlineStatusCacheTimeout . No need to update the cache so often - it only overloads your server..

Offline squirrel  
#4 Posted : Saturday, March 12, 2011 7:36:09 AM(UTC)
squirrel


Rank: YAF Leader

Reputation:

Medals: YAF.NET Supporter: Loves YAF.NET!YAF.NET Supporter: Supports the YAF.NET project with a contribution.YAF.NET Purple Supporter: Purple heart for being an Asset to the YAF.NET Community.YAF.NET Supporter: Supports our efforts. Thank you.Medal of Honor for the Support King: A huge help to the YAF.NET community!

Joined: 1/14/2010(UTC)
Posts: 954

Thanks: 251 times
Was thanked: 171 time(s) in 162 post(s)
Tommy - that is a really neat feature -- thank you very much for adding the code here to the forums -- I'm going to implement this on our server when we get ready to move our live site to the 1.9.5.5 update.

I have one question -- as I can tell your .NET skills are much better than mine.

Our old forums were Snitz based, and had the 'Birthdays' mod installed, which would display user birthdays for a given day, and also had 'upcoming birthdays' and 'recent birthdays' -- do you think you could give me some tips when you have time on how I could implement this into our forums? Thanks!
If you can't find it using the forum search, try my signature link -- searches this site using Google: Google is my Friend
Offline tommy382  
#5 Posted : Saturday, March 12, 2011 1:48:50 PM(UTC)
tommy382


Rank: YAF Commander

Reputation:

Joined: 4/11/2008(UTC)
Posts: 94

Thanks: 10 times
Was thanked: 3 time(s) in 3 post(s)
Originally Posted by: bbobb Go to Quoted Post
tommy382 Offline ThumpUp .Just a notion -you use OnlineStatusCacheTimeout . No need to update the cache so often - it only overloads your server..


Thanks for the tips, I thought that was the 5 minutes interval but I was wrong. I updated the above code to use ForumStatisticsCacheTimeout - 5 minutes by default.
Offline tommy382  
#6 Posted : Saturday, March 12, 2011 2:02:26 PM(UTC)
tommy382


Rank: YAF Commander

Reputation:

Joined: 4/11/2008(UTC)
Posts: 94

Thanks: 10 times
Was thanked: 3 time(s) in 3 post(s)
Originally Posted by: squirrel Go to Quoted Post
Tommy - that is a really neat feature -- thank you very much for adding the code here to the forums -- I'm going to implement this on our server when we get ready to move our live site to the 1.9.5.5 update.

I have one question -- as I can tell your .NET skills are much better than mine.

Our old forums were Snitz based, and had the 'Birthdays' mod installed, which would display user birthdays for a given day, and also had 'upcoming birthdays' and 'recent birthdays' -- do you think you could give me some tips when you have time on how I could implement this into our forums? Thanks!

Have you looked at the DB to see where the Birthday info is stored? I don't see it under the yaf_User table. Just need the 2 queries to get the "recent" and "coming" birthdays. Then write a control to display the users (styled nicks support if enabled). One tricky part is to incorporate the time zone offset. Look at how the "Birthday" field in the "profile" page did it - it did took user timezone into consideration when computing the birthday.
Offline bbobb  
#7 Posted : Saturday, March 12, 2011 2:13:56 PM(UTC)
bbobb


Rank: YAF Developer

Reputation:

Medals: Medal of Honor Key: Given to pillars of the community who are key players in the YAF community and project.Medal of Honor for a YAF Database Key Player: Holds the key to YAF database. Bow down!Medal of Honor for the Support King: Given for answering tons of support questions and generally helping the community.Medal of Honor for the Support Knight: Given to a community member who has answered lots of support questions.

Joined: 10/21/2008(UTC)
Posts: 1,543

Thanks: 46 times
Was thanked: 281 time(s) in 248 post(s)
prov_Profile Birthday
Offline tommy382  
#8 Posted : Saturday, March 12, 2011 8:06:19 PM(UTC)
tommy382


Rank: YAF Commander

Reputation:

Joined: 4/11/2008(UTC)
Posts: 94

Thanks: 10 times
Was thanked: 3 time(s) in 3 post(s)
Update: The fix to the "duplicate control id" I posted earlier failed in some cases. Ironically, it failed on the pages w/o the statistics data (i.e. a forum category page). Not sure why the "Active Users" controls were rendered in those pages. I updated the fix above to add a unique ID instead of using the id "UserLink" + UserId since multiple instances of the styled nick userlink will cause two controls to have the same id.

So the fix is just one line:
userLink.ID = "UserLink" + this.UniqueID + userLink.UserID;
Offline ruek23  
#9 Posted : Monday, March 14, 2011 4:13:14 PM(UTC)
ruek23


Rank: YAF Lover

Reputation:

Joined: 3/5/2010(UTC)
Posts: 67

Thanks: 9 times
Was thanked: 6 time(s) in 6 post(s)
Thanks for this tommy382

I implemented this on my forum today... looks awesome and works very well.

Had to do some modifications for 1.9.5.5, added to the stored procedure and added the text stuff into the Language file.

all the ground work was yours though
Offline tommy382  
#10 Posted : Wednesday, March 16, 2011 3:40:25 AM(UTC)
tommy382


Rank: YAF Commander

Reputation:

Joined: 4/11/2008(UTC)
Posts: 94

Thanks: 10 times
Was thanked: 3 time(s) in 3 post(s)
Originally Posted by: ruek23 Go to Quoted Post
Thanks for this tommy382

I implemented this on my forum today... looks awesome and works very well.

Had to do some modifications for 1.9.5.5, added to the stored procedure and added the text stuff into the Language file.

all the ground work was yours though

Nice to hear ThumpUp. Be careful with the implementation I posted above though - it would still fail in some cases (pay attention to the logs). My final solution is below and works perfectly. The forum has been up for several days now and got relatively high traffic and not a single log related to this control conflict issue.

Instead of using this.UniqueID, use a unique instant id per "active users" control. The uniqueID could still cause control ID conflict sometimes - not sure why but log data proved it.

Code:
userLink.ID = "UserLink" + this.InstantId + userLink.UserID;


So you will to add a new property called "InstantId to the ActiveUsers.cs file.
Code:
    /// <summary>
    /// The Instant ID for this control.
    /// </summary>
    /// <remarks>
    /// Multiple instants of this control can exist in the same page but
    /// each must have a different instant ID. Not specifying an Instant ID
    /// default to the ID being string.Empty.
    /// </remarks>
    public string InstantId
    {
      get
      {
        //return string.empty for null.
        return (this.ViewState["InstantId"] as string) + "";
      }
      set
      {
        this.ViewState["InstantId"] = value;
      }
    }


Then in the page where you want to include the control, u can declare something like this:
This one is existing code (w/o specifying the InstantID) so the InstantID is string.Empty by default:
Code:
<YAF:ActiveUsers ID="ActiveUsers1" runat="server"></YAF:ActiveUsers>


On the same page, I can have another instant like this:
Code:
<YAF:ActiveUsers ID="activeUsersOneDay" runat="server" InstantId="ActiveUsersOneDay" />

Edited by user Wednesday, March 16, 2011 3:41:29 AM(UTC)  | Reason: Not specified

Offline ruek23  
#11 Posted : Wednesday, March 16, 2011 4:13:31 AM(UTC)
ruek23


Rank: YAF Lover

Reputation:

Joined: 3/5/2010(UTC)
Posts: 67

Thanks: 9 times
Was thanked: 6 time(s) in 6 post(s)
Originally Posted by: tommy382 Go to Quoted Post
Originally Posted by: ruek23 Go to Quoted Post


Code:
userLink.ID = "UserLink" + this.InstantId + userLink.UserID;




hey tommy...
thanks
I was talking crap before hence edit Smile

Edited by user Wednesday, March 16, 2011 11:36:58 AM(UTC)  | Reason: Not specified

Offline tommy382  
#12 Posted : Wednesday, March 16, 2011 11:38:25 AM(UTC)
tommy382


Rank: YAF Commander

Reputation:

Joined: 4/11/2008(UTC)
Posts: 94

Thanks: 10 times
Was thanked: 3 time(s) in 3 post(s)
Originally Posted by: ruek23 Go to Quoted Post

hey tommy...

i used

Code:
userLink.ID = "UserLink" + this.activeUsersOneDay.ID + userLink.UserID;


which means the userlink is basically associated to the control you are using it in.

Which class are you using that line in? The "ActiveUsers.cs" class can't tell its instant name (the name of the object in which it's an instance of). That syntax suggests that you are using it at the ForumStatistics class? Are you sub-classing the UserLink class and change the Control.ID property? Interesting approach ThumpUp.
Offline ruek23  
#13 Posted : Wednesday, March 16, 2011 12:50:23 PM(UTC)
ruek23


Rank: YAF Lover

Reputation:

Joined: 3/5/2010(UTC)
Posts: 67

Thanks: 9 times
Was thanked: 6 time(s) in 6 post(s)
Originally Posted by: tommy382 Go to Quoted Post
Originally Posted by: ruek23 Go to Quoted Post

hey tommy...

i used

Code:
userLink.ID = "UserLink" + this.activeUsersOneDay.ID + userLink.UserID;


which means the userlink is basically associated to the control you are using it in.

Which class are you using that line in? The "ActiveUsers.cs" class can't tell its instant name (the name of the object in which it's an instance of). That syntax suggests that you are using it at the ForumStatistics class? Are you sub-classing the UserLink class and change the Control.ID property? Interesting approach ThumpUp.


Sorry tommy I was at work so didn't have the code in front of me..

I tried the above by adding a property to the ActiveUsers.cs called ParentControlName which is set in the forum stats page.

This is then used like

Code:
userLink.ID = "UserLink" + ParentControlName  + userLink.UserID;


the problem is I was still getting issues. so have taken out this bit of the code...

Offline tommy382  
#14 Posted : Wednesday, March 16, 2011 1:01:48 PM(UTC)
tommy382


Rank: YAF Commander

Reputation:

Joined: 4/11/2008(UTC)
Posts: 94

Thanks: 10 times
Was thanked: 3 time(s) in 3 post(s)
Ok, that makes sense now. This approach is basically the same as mine "instant id" approach. It works great. ThumpUp
Rss Feed  Atom Feed
Users browsing this topic
guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

Notification

Icon
Error