Skip to content

Commit

Permalink
Adding package download statistics to Home page
Browse files Browse the repository at this point in the history
  • Loading branch information
pranavkm committed Jun 12, 2012
1 parent 764a1f2 commit da9fee5
Show file tree
Hide file tree
Showing 13 changed files with 218 additions and 13 deletions.
4 changes: 4 additions & 0 deletions Website/App_Start/ContainerBindings.cs
Expand Up @@ -207,6 +207,10 @@ public override void Load()
Bind<IUserByUsernameQuery>()
.To<UserByUsernameQuery>()
.InRequestScope();

Bind<IAggregateStatsService>()
.To<AggregateStatsService>()
.InRequestScope();
Bind<IPackageIdsQuery>()
.To<PackageIdsQuery>()
.InRequestScope();
Expand Down
5 changes: 5 additions & 0 deletions Website/App_Start/Routes.cs
Expand Up @@ -14,6 +14,11 @@ public static void RegisterRoutes(RouteCollection routes)
"",
MVC.Pages.Home());

routes.MapRoute(
RouteName.Stats,
"stats",
MVC.Pages.Stats());

routes.Add(new JsonRoute("json/{controller}"));

routes.MapRoute(
Expand Down
29 changes: 28 additions & 1 deletion Website/Content/Site.css
Expand Up @@ -390,7 +390,34 @@ header.main {
border-color: #4585aa;
text-decoration: none;
}


/* Aggregate Stats */
.aggstats {
background: #555;
display: none;
}

.aggstats .stat {
display: inline-block;
*zoom: 1;
color: #bbb;
font-weight: bold;
text-align: center;
padding: 0.5em 0;
width: 33%;
margin: 0;
}
.aggstats .num {
font-size: 4em;
color: #f9f9f9;
font-family: monospace;
display: block;
line-height: 0.9em;
}

.aggstats .num > span {
position: relative;
}

/* Account/Actions */
#actions h1 {
Expand Down
21 changes: 21 additions & 0 deletions Website/Controllers/PagesController.cs
@@ -1,9 +1,17 @@
using System.Web.Mvc;
using System.Web.UI;

namespace NuGetGallery
{
public partial class PagesController : Controller
{
private readonly IAggregateStatsService statsSvc;

public PagesController(IAggregateStatsService statsSvc)
{
this.statsSvc = statsSvc;
}

public virtual ActionResult Home()
{
return View();
Expand All @@ -18,5 +26,18 @@ public virtual ActionResult Privacy()
{
return View();
}

[HttpGet]
[OutputCache(VaryByParam = "None", Duration = 120, Location = OutputCacheLocation.Server)]
public virtual JsonResult Stats()
{
var stats = statsSvc.GetAggregateStats();
return Json(new
{
Downloads = stats.Downloads.ToString("#,#"),
UniquePackages = stats.UniquePackages.ToString("#,#"),
TotalPackages = stats.TotalPackages.ToString("#,#")
}, JsonRequestBehavior.AllowGet);
}
}
}
9 changes: 6 additions & 3 deletions Website/PagesController.generated.cs
Expand Up @@ -22,9 +22,6 @@
using T4MVC;
namespace NuGetGallery {
public partial class PagesController {
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public PagesController() { }

[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected PagesController(Dummy d) { }

Expand All @@ -50,6 +47,7 @@ public class ActionNamesClass {
public readonly string Home = "Home";
public readonly string Terms = "Terms";
public readonly string Privacy = "Privacy";
public readonly string Stats = "Stats";
}


Expand Down Expand Up @@ -83,6 +81,11 @@ public class T4MVC_PagesController: NuGetGallery.PagesController {
return callInfo;
}

public override System.Web.Mvc.JsonResult Stats() {
var callInfo = new T4MVC_JsonResult(Area, Name, ActionNames.Stats);
return callInfo;
}

}
}

Expand Down
1 change: 1 addition & 0 deletions Website/RouteNames.cs
Expand Up @@ -12,6 +12,7 @@ public static class RouteName
public const string DownloadPackage = "DownloadPackage";
public const string DownloadNuGetExe = "DownloadNuGetExe";
public const string Home = "Home";
public const string Stats = "Stats";
public const string Policies = "Policies";
public const string ListPackages = "ListPackages";
public const string Authentication = "SignIn";
Expand Down
53 changes: 53 additions & 0 deletions Website/Scripts/stats.js
@@ -0,0 +1,53 @@
function getStats() {
$.get('/Stats', function(data) {
var section = $('section.aggstats');
section.show();
update(data, 'UniquePackages');
update(data, 'Downloads');
update(data, 'TotalPackages');
})
setTimeout(getStats, 30000);
}

function update(data, key) {
var value = data[key].toString();
var self = $('#' + key);
var currentValue = $.trim(self.text().replace(/\s/g, ''));
if (currentValue != value) {
var length = value.length;
var currLength = currentValue.length;
var items = self.children('span');

if (currLength > length) {
while (items.length > length) {
items.first().remove();
items = self.children('span');
}
}
else if (currLength < length) {
var i;
for (i = currLength; i < length; i++) {
self.prepend('<span>' + value.charAt(length - i - 1) + '</span>');
}
items = self.children('span');
currentValue = $.trim(self.text().replace(/\s/g, ''));
currLength = currentValue.length;
}

$.each(value.split('').reverse(), function (i, e) {
var c = (i < currLength) ? currentValue.charAt(currLength - i - 1) : '';
if (c != e) {
var el = $(items[length - i - 1]);
animateEl(el, e);
}
});
}

function animateEl(el, v) {
v = v || '';
var parent = e.parent();
el.animate({ top: 0.3 * parseInt(parent.height()) }, 350, 'linear', function () {
$(this).html(v).css({ top: -0.8 * parseInt(parent.height()) }).animate({ top: 0 }, 350, 'linear')
});
}
}
39 changes: 39 additions & 0 deletions Website/Services/AggregateStatsService.cs
@@ -0,0 +1,39 @@
using System.Data;

namespace NuGetGallery
{
public class AggregateStatsService : IAggregateStatsService
{
public AggregateStats GetAggregateStats()
{
using (var dbContext = new EntitiesContext())
{
var database = dbContext.Database;
using (var command = database.Connection.CreateCommand())
{
command.CommandText = @"Select
(Select Count([Key]) from PackageRegistrations) as UniquePackages,
(Select Count([Key]) from Packages where Listed = 1) as TotalPackages,
(
(Select Sum(DownloadCount) from Packages) +
(Select Count([Key]) from PackageStatistics where [Key] >
(Select DownloadStatsLastAggregatedId FROM GallerySettings)
)
) as DownloadCount";

database.Connection.Open();
using (var reader = command.ExecuteReader(CommandBehavior.CloseConnection | CommandBehavior.SingleRow))
{
reader.Read();
return new AggregateStats
{
UniquePackages = reader.GetInt32(0),
TotalPackages = reader.GetInt32(1),
Downloads = reader.GetInt32(2),
};
}
}
}
}
}
}
8 changes: 8 additions & 0 deletions Website/Services/IAggregateStatsService.cs
@@ -0,0 +1,8 @@

namespace NuGetGallery
{
public interface IAggregateStatsService
{
AggregateStats GetAggregateStats();
}
}
19 changes: 17 additions & 2 deletions Website/T4MVC.cs
Expand Up @@ -253,7 +253,8 @@ public static class T4Extensions {
result.RouteValueDictionary.Add("Action", action);
}

public static bool FileExists(string virtualPath) {
public static bool FileExists(string virtualPath)
{
if (!HostingEnvironment.IsHosted) return false;
string filePath = HostingEnvironment.MapPath(virtualPath);
return System.IO.File.Exists(filePath);
Expand Down Expand Up @@ -302,7 +303,19 @@ public class T4MVC_ActionResult : System.Web.Mvc.ActionResult, IT4MVCActionResul
public string Action { get; set; }
public RouteValueDictionary RouteValueDictionary { get; set; }
}
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
public class T4MVC_JsonResult : System.Web.Mvc.JsonResult, IT4MVCActionResult
{
public T4MVC_JsonResult(string area, string controller, string action)
: base()
{
this.InitMVCT4Result(area, controller, action);
}

public string Controller { get; set; }
public string Action { get; set; }
public RouteValueDictionary RouteValueDictionary { get; set; }
}


namespace Links {
Expand All @@ -311,6 +324,8 @@ public static class Scripts {
private const string URLPATH = "~/Scripts";
public static string Url() { return T4MVCHelpers.ProcessVirtualPath(URLPATH); }
public static string Url(string fileName) { return T4MVCHelpers.ProcessVirtualPath(URLPATH + "/" + fileName); }
public static readonly string Home_js = T4MVCHelpers.IsProduction() && T4Extensions.FileExists(URLPATH + "/Home.min.js") ? Url("Home.min.js") : Url("Home.js");

public static readonly string jquery_1_6_2_vsdoc_js = T4MVCHelpers.IsProduction() && T4Extensions.FileExists(URLPATH + "/jquery-1.6.2-vsdoc.min.js") ? Url("jquery-1.6.2-vsdoc.min.js") : Url("jquery-1.6.2-vsdoc.js");

public static readonly string jquery_1_6_2_js = T4MVCHelpers.IsProduction() && T4Extensions.FileExists(URLPATH + "/jquery-1.6.2.min.js") ? Url("jquery-1.6.2.min.js") : Url("jquery-1.6.2.js");
Expand All @@ -327,7 +342,7 @@ public static class Scripts {
public static readonly string modernizr_2_0_6_development_only_js = T4MVCHelpers.IsProduction() && T4Extensions.FileExists(URLPATH + "/modernizr-2.0.6-development-only.min.js") ? Url("modernizr-2.0.6-development-only.min.js") : Url("modernizr-2.0.6-development-only.js");

public static readonly string ZeroClipboard_js = T4MVCHelpers.IsProduction() && T4Extensions.FileExists(URLPATH + "/ZeroClipboard.min.js") ? Url("ZeroClipboard.min.js") : Url("ZeroClipboard.js");

public static readonly string ZeroClipboard_swf = Url("ZeroClipboard.swf");
}

Expand Down
12 changes: 12 additions & 0 deletions Website/ViewModels/AggregateStats.cs
@@ -0,0 +1,12 @@

namespace NuGetGallery
{
public class AggregateStats
{
public long Downloads { get; set; }

public int UniquePackages { get; set; }

public int TotalPackages { get; set; }
}
}
20 changes: 20 additions & 0 deletions Website/Views/Pages/Home.cshtml
Expand Up @@ -11,6 +11,18 @@
<img src="@Url.Content("~/content/images/hero.png")" alt="NuGet GUI Window" />
</section>

<section class="aggstats">
<span class="stat">
<span id="UniquePackages" class="num"></span> unique packages
</span>
<span class="stat">
<span id="Downloads" class="num"></span>total downloads
</span>
<span class="stat">
<span id="TotalPackages" class="num"></span>total packages
</span>
</section>

<section class="release">
<h2>NuGet 1.8 Released</h2>
<p>
Expand All @@ -34,3 +46,11 @@
<a title="Creating and submitting a package" href="http://docs.nuget.org/docs/creating-packages/creating-and-publishing-a-package">how to
create and publish a package</a>. If you don&rsquo;t plan on submitting a package, there&rsquo;s no need to register.</p>
</section>

@section BottomScripts
{
<script src="@Url.Content("~/Scripts/stats.js")"></script>
<script>
$(getStats);
</script>
}
11 changes: 4 additions & 7 deletions Website/Website.csproj
Expand Up @@ -366,12 +366,14 @@
<Compile Include="Services\IFileStorageService.cs" />
<Compile Include="Services\IIndexingService.cs" />
<Compile Include="Services\INuGetExeDownloaderService.cs" />
<Compile Include="Services\IAggregateStatsService.cs" />
<Compile Include="Services\ISearchService.cs" />
<Compile Include="Services\IUploadFileService.cs" />
<Compile Include="Services\NuGetExeDownloaderService.cs" />
<Compile Include="Services\PackageFileService.cs" />
<Compile Include="RequireRemoteHttpsAttribute.cs" />
<Compile Include="Services\PackageSearchResults.cs" />
<Compile Include="Services\AggregateStatsService.cs" />
<Compile Include="Services\TestableStorageClientException.cs" />
<Compile Include="Services\UploadFileService.cs" />
<Compile Include="SharedController.generated.cs">
Expand All @@ -386,6 +388,7 @@
<DependentUpon>T4MVC.tt</DependentUpon>
</Compile>
<Compile Include="ViewModels\AccountViewModel.cs" />
<Compile Include="ViewModels\AggregateStats.cs" />
<Compile Include="ViewModels\CuratedFeedViewModel.cs" />
<Compile Include="ViewModels\EditProfileViewModel.cs" />
<Compile Include="ViewModels\EmailConfirmationModel.cs" />
Expand Down Expand Up @@ -773,6 +776,7 @@
<Content Include="DynamicData\Site.css" />
<Content Include="Errors\Error.html" />
<Content Include="favicon.ico" />
<Content Include="Scripts\stats.js" />
<Content Include="Scripts\jquery-1.6.2-vsdoc.js" />
<Content Include="Scripts\jquery-1.6.2.js" />
<Content Include="Scripts\jquery-1.6.2.min.js" />
Expand Down Expand Up @@ -839,13 +843,6 @@
<Compile Include="Infrastructure\Lucene\LuceneSearchService.cs" />
<Content Include="Views\CuratedFeeds\CuratedFeed.cshtml" />
<Content Include="Views\CuratedPackages\CreateCuratedPackageForm.cshtml" />
<None Include="_bin_deployableAssemblies\Microsoft.Web.Infrastructure.dll" />
<None Include="_bin_deployableAssemblies\System.Web.WebPages.Razor.dll" />
<None Include="_bin_deployableAssemblies\System.Web.WebPages.dll" />
<None Include="_bin_deployableAssemblies\System.Web.WebPages.Deployment.dll" />
<None Include="_bin_deployableAssemblies\System.Web.Razor.dll" />
<None Include="_bin_deployableAssemblies\System.Web.Helpers.dll" />
<None Include="_bin_deployableAssemblies\System.Web.Mvc.dll" />
</ItemGroup>
<ItemGroup>
<Content Include="packages.config">
Expand Down

0 comments on commit da9fee5

Please sign in to comment.