Skip to content

Commit

Permalink
ADBench web view application (#144)
Browse files Browse the repository at this point in the history
* ADBench web view application is implemented
  • Loading branch information
mikhailnikolaev committed Nov 7, 2019
1 parent adcdac0 commit 53299b8
Show file tree
Hide file tree
Showing 13 changed files with 395 additions and 0 deletions.
25 changes: 25 additions & 0 deletions ADBench/ADBenchWebViewer/ADBenchWebViewer.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29209.62
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ADBenchWebViewer", "ADBenchWebViewer\ADBenchWebViewer.csproj", "{EFF1419F-1810-4320-BE10-34024AAF626D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{EFF1419F-1810-4320-BE10-34024AAF626D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EFF1419F-1810-4320-BE10-34024AAF626D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EFF1419F-1810-4320-BE10-34024AAF626D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EFF1419F-1810-4320-BE10-34024AAF626D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C7D839A1-5127-456C-8045-04853FB7028B}
EndGlobalSection
EndGlobal
16 changes: 16 additions & 0 deletions ADBench/ADBenchWebViewer/ADBenchWebViewer/ADBenchWebViewer.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>


<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.Azure.Storage.Blob" Version="11.1.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.4" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ADBenchWebViewer.Models;
using Microsoft.Azure.Storage.Blob;

namespace ADBenchWebViewer.Controllers
{
/// <summary>
/// Contains helping methods for working with Azure Blob.
/// </summary>
public class AzureBlobHelper : IRunInfoProvider
{
private const string staticSubdirName = "static";
private const string plotlySubdirName = "plotly";

private readonly CloudBlobContainer rootContatiner;

public AzureBlobHelper(string containerAddress)
{
var containerUri = new Uri(containerAddress);
rootContatiner = new CloudBlobContainer(containerUri);
}

public IDictionary<string, RunInfo> GetRunsInfo()
{
return rootContatiner.ListBlobs()
.Where(item => item is CloudBlobDirectory)
.Select(item => item as CloudBlobDirectory)
.OrderByDescending(dir => dir.Prefix)
.ToDictionary(
dir => dir.Prefix,
dir =>
{
var parts = dir.Prefix.Trim('/').Split('_');
return new RunInfo()
{
Date = parts[0].Replace('-', '.'),
Time = parts[1].Replace('-', ':'),
Commit = parts[2],
CloudBlobDirectory = dir
};
}
);
}

public IDictionary<string, IEnumerable<PlotInfo>> GetPlotsInfo(string dirName)
{
var cloudDirectory = GetRunsInfo()[dirName].CloudBlobDirectory;
var staticPlotDir = cloudDirectory.GetDirectoryReference(staticSubdirName);
var plotlyPlotDir = cloudDirectory.GetDirectoryReference(plotlySubdirName);

var staticPlots = GetPlotBlobs(staticPlotDir);
var plotlyPlots = GetPlotBlobs(plotlyPlotDir);

return staticPlots
.Zip(plotlyPlots, (first, second) => (first.Key, val: (staticPlots: first.Value, plotlyPlots: second.Value)))
.ToDictionary(
item => CapitalFirstLetter(item.Key),
item => item.val.staticPlots
.Zip(
item.val.plotlyPlots,
(st, pl) => new PlotInfo()
{
DisplayName = GetDisplayName(pl.Name),
StaticPlotUrl = st.Uri.ToString(),
PlotlyPlotUrl = pl.Uri.ToString()
}
)
);

IDictionary<string, IEnumerable<CloudBlob>> GetPlotBlobs(CloudBlobDirectory cloudDir) =>
cloudDir.ListBlobs()
.Where(item => item is CloudBlobDirectory)
.Select(item => item as CloudBlobDirectory)
.Select(dir => (name: dir.Prefix.Trim('/').Split('/').Last(), directory: dir))
.OrderBy(pair => pair.name)
.ToDictionary(
pair => pair.name,
pair => pair.directory.ListBlobs()
.Where(item => item is CloudBlob)
.Select(item => item as CloudBlob)
);

string GetDisplayName(string name) => System.IO.Path.GetFileNameWithoutExtension(name.Split('/').Last());

string CapitalFirstLetter(string str) => char.ToUpper(str[0]) + str.Substring(1);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using ADBenchWebViewer.Models;
using System.Collections.Generic;

namespace ADBenchWebViewer.Controllers
{
/// <summary>
/// Provides access to run info and run plots.
/// </summary>
public interface IRunInfoProvider
{
/// <summary>
/// Returns info about runs that storage holds.
/// </summary>
/// <returns></returns>
IDictionary<string, RunInfo> GetRunsInfo();

/// <summary>
/// Returns info about all files contain plots in this subdirectory.
/// </summary>
/// <param name="dir">Cloud root subdirectory files are searched in.</param>
/// <returns>Dictionary whose keys are base subdirectory name.</returns>
IDictionary<string, IEnumerable<PlotInfo>> GetPlotsInfo(string dirName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Mvc;

namespace ADBenchWebViewer.Controllers
{
public class PlotsController : Controller
{
private readonly IRunInfoProvider runInfoProvider;

public PlotsController(IRunInfoProvider runInfoProvider) => this.runInfoProvider = runInfoProvider;

public IActionResult Index()
{
var dirInfo = runInfoProvider.GetRunsInfo();
return View(dirInfo);
}

public IActionResult GetStatic(string dir)
{
return View(runInfoProvider.GetPlotsInfo(dir));
}

public IActionResult GetPlotly(string dir)
{
return View(runInfoProvider.GetPlotsInfo(dir));
}
}
}
23 changes: 23 additions & 0 deletions ADBench/ADBenchWebViewer/ADBenchWebViewer/Models/PlotsInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace ADBenchWebViewer.Models
{
/// <summary>
/// Contatins information about single plot of the run.
/// </summary>
public class PlotInfo
{
/// <summary>
/// Display name of the plot.
/// </summary>
public string DisplayName { get; set; }

/// <summary>
/// URL of the static version of the plot.
/// </summary>
public string StaticPlotUrl { get; set; }

/// <summary>
/// URL of the HTML file with plotly version of the plot.
/// </summary>
public string PlotlyPlotUrl { get; set; }
}
}
30 changes: 30 additions & 0 deletions ADBench/ADBenchWebViewer/ADBenchWebViewer/Models/RunInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Microsoft.Azure.Storage.Blob;

namespace ADBenchWebViewer.Models
{
/// <summary>
/// Representation of the information about a single run.
/// </summary>
public class RunInfo
{
/// <summary>
/// Date when run is performed.
/// </summary>
public string Date { get; set; }

/// <summary>
/// Time when run is performed.
/// </summary>
public string Time { get; set; }

/// <summary>
/// Hash of the latest commit that repository has when run is performed.
/// </summary>
public string Commit { get; set; }

/// <summary>
/// Cloud blob directory contatins the run plots.
/// </summary>
public CloudBlobDirectory CloudBlobDirectory { get; set; }
}
}
17 changes: 17 additions & 0 deletions ADBench/ADBenchWebViewer/ADBenchWebViewer/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace ADBenchWebViewer
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
60 changes: 60 additions & 0 deletions ADBench/ADBenchWebViewer/ADBenchWebViewer/Startup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using ADBenchWebViewer.Controllers;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace ADBenchWebViewer
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});

services.AddSingleton((IRunInfoProvider)new AzureBlobHelper(Configuration["blobContainerUrl"]));
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();

app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Plots}/{action=Index}/{id?}");
});
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@model IDictionary<string, IEnumerable<ADBenchWebViewer.Models.PlotInfo>>

<style>
.title {
font-size: 25pt;
font-weight: 900;
}
.ref {
font-size: 15pt;
font-weight: 600;
}
.block {
margin-left: 40px;
}
</style>

@foreach (var (type, infos) in Model)
{
<div class="title">@type</div>
<div class="block">
@foreach (var info in infos)
{
<div><a href="@info.PlotlyPlotUrl" type="text/html">@info.DisplayName</a></div>
}
</div>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@model IDictionary<string, IEnumerable<ADBenchWebViewer.Models.PlotInfo>>

<style>
.graph {
width: 70%;
}
.block {
border: double
}
.plotly-ref {
font-size: 15pt;
font-weight: 700;
}
</style>

@foreach (var (type, infos) in Model)
{
<h1>@type</h1>
@foreach (var info in infos)
{
<div class="block" align="center">
<img class="graph" src="@info.StaticPlotUrl" />
<div>
<a class="plotly-ref" href="@info.PlotlyPlotUrl">Plotly version</a>
</div>
</div>
}
}

0 comments on commit 53299b8

Please sign in to comment.