Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Adding package download statistics to Home page

  • Loading branch information...
commit da9fee5ac12c13129c2dcfd666942f0c8c40fd9d 1 parent 764a1f2
@pranavkm pranavkm authored
View
4 Website/App_Start/ContainerBindings.cs
@@ -207,6 +207,10 @@ public override void Load()
Bind<IUserByUsernameQuery>()
.To<UserByUsernameQuery>()
.InRequestScope();
+
+ Bind<IAggregateStatsService>()
+ .To<AggregateStatsService>()
+ .InRequestScope();
Bind<IPackageIdsQuery>()
.To<PackageIdsQuery>()
.InRequestScope();
View
5 Website/App_Start/Routes.cs
@@ -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(
View
29 Website/Content/Site.css
@@ -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 {
View
21 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();
@@ -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);
+ }
}
}
View
9 Website/PagesController.generated.cs
@@ -23,9 +23,6 @@
namespace NuGetGallery {
public partial class PagesController {
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
- public PagesController() { }
-
- [GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
protected PagesController(Dummy d) { }
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
@@ -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";
}
@@ -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;
+ }
+
}
}
View
1  Website/RouteNames.cs
@@ -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";
View
53 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')
+ });
+ }
+}
View
39 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),
+ };
+ }
+ }
+ }
+ }
+ }
+}
View
8 Website/Services/IAggregateStatsService.cs
@@ -0,0 +1,8 @@
+
+namespace NuGetGallery
+{
+ public interface IAggregateStatsService
+ {
+ AggregateStats GetAggregateStats();
+ }
+}
View
19 Website/T4MVC.cs
@@ -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);
@@ -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 {
@@ -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");
@@ -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");
}
View
12 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; }
+ }
+}
View
20 Website/Views/Pages/Home.cshtml
@@ -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>
@@ -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>
+}
View
11 Website/Website.csproj
@@ -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">
@@ -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" />
@@ -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" />
@@ -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">
Please sign in to comment.
Something went wrong with that request. Please try again.