├── .gitattributes ├── .gitignore ├── DotNetStatus.sln ├── LICENSE ├── NuGet.config ├── README.md ├── global.json └── src └── DotNetStatus ├── ApplicationInsights.config ├── Controllers ├── DataController.cs ├── FxApiController.cs ├── HomeController.cs ├── SubmissionController.cs └── UsageController.cs ├── DotNetStatus.xproj ├── JSLintNet.json ├── Microsoft.Fx.Portability.ObjectModel ├── BreakingChangeAnalyzerStatusChartColors.cs └── ChartJSDataItem.cs ├── Program.cs ├── Properties ├── debugSettings.json └── launchSettings.json ├── Services └── PortabilityToolsStatusService.cs ├── Startup.cs ├── Views ├── Data │ ├── Analyzers.cshtml │ ├── BreakingChanges.cshtml │ ├── Index.cshtml │ ├── KeyValuePair.cshtml │ └── RollUp.cshtml ├── FxApi │ └── Index.cshtml ├── Home │ └── Index.cshtml ├── Shared │ ├── Error.cshtml │ └── _Layout.cshtml ├── Submission │ ├── Index.cshtml │ ├── _Find.cshtml │ └── _SubmissionResult.cshtml ├── Usage │ ├── Index.cshtml │ ├── _Error.cshtml │ ├── _Legend.cshtml │ ├── _Usage.cshtml │ └── _UsageGrid.cshtml ├── _ViewImports.cshtml └── _ViewStart.cshtml ├── appsettings.development.json ├── appsettings.json ├── assets ├── css │ ├── DotNetStatus.css │ ├── PopoverStyles.css │ ├── navbar.css │ ├── search.css │ └── usageicons.css └── js │ ├── AppInsights.js │ ├── DotNetStatus.js │ ├── PopoverHelpers.js │ ├── Search.js │ └── ie10-viewport-bug-workaround.js ├── bower.json ├── gulpfile.js ├── package.json ├── project.json ├── web.config └── wwwroot └── img ├── dotnet.ico └── loader.gif /.gitattributes: -------------------------------------------------------------------------------- 1 | *.doc diff=astextplain 2 | *.DOC diff=astextplain 3 | *.docx diff=astextplain 4 | *.DOCX diff=astextplain 5 | *.dot diff=astextplain 6 | *.DOT diff=astextplain 7 | *.pdf diff=astextplain 8 | *.PDF diff=astextplain 9 | *.rtf diff=astextplain 10 | *.RTF diff=astextplain 11 | 12 | *.jpg binary 13 | *.png binary 14 | *.gif binary 15 | 16 | *.cs text=auto diff=csharp 17 | *.vb text=auto 18 | *.resx text=auto 19 | *.c text=auto 20 | *.cpp text=auto 21 | *.cxx text=auto 22 | *.h text=auto 23 | *.hxx text=auto 24 | *.py text=auto 25 | *.rb text=auto 26 | *.java text=auto 27 | *.html text=auto 28 | *.htm text=auto 29 | *.css text=auto 30 | *.scss text=auto 31 | *.sass text=auto 32 | *.less text=auto 33 | *.js text=auto 34 | *.lisp text=auto 35 | *.clj text=auto 36 | *.sql text=auto 37 | *.php text=auto 38 | *.lua text=auto 39 | *.m text=auto 40 | *.asm text=auto 41 | *.erl text=auto 42 | *.fs text=auto 43 | *.fsx text=auto 44 | *.hs text=auto 45 | 46 | *.kproj text=auto 47 | *.csproj text=auto 48 | *.vbproj text=auto 49 | *.fsproj text=auto 50 | *.dbproj text=auto 51 | *.sln text=auto eol=crlf 52 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | syntax: glob 2 | *.user 3 | *.suo 4 | *.dbmdl 5 | Bin 6 | bin 7 | obj 8 | CustomTasks 9 | msbuild.log 10 | packages 11 | csx 12 | *.log 13 | *.jrs 14 | *.chk 15 | *.sln.ide 16 | *.coverage 17 | TestResults 18 | FakesAssemblies 19 | rcf 20 | *~ 21 | *.sln.ide 22 | *.metaproj* 23 | *.swp 24 | .vs 25 | bower_components 26 | node_modules 27 | /src/DotNetStatus/wwwroot 28 | project.lock.json -------------------------------------------------------------------------------- /DotNetStatus.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.23107.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "DotNetStatus", "src\DotNetStatus\DotNetStatus.xproj", "{156E5AB6-C13D-4D12-AD10-2AFA192DB3B5}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{31984862-8C60-49B8-862D-2B001B47EA48}" 9 | ProjectSection(SolutionItems) = preProject 10 | global.json = global.json 11 | LICENSE = LICENSE 12 | NuGet.config = NuGet.config 13 | README.md = README.md 14 | EndProjectSection 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Release|Any CPU = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {156E5AB6-C13D-4D12-AD10-2AFA192DB3B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {156E5AB6-C13D-4D12-AD10-2AFA192DB3B5}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {156E5AB6-C13D-4D12-AD10-2AFA192DB3B5}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {156E5AB6-C13D-4D12-AD10-2AFA192DB3B5}.Release|Any CPU.Build.0 = Release|Any CPU 26 | EndGlobalSection 27 | GlobalSection(SolutionProperties) = preSolution 28 | HideSolutionNode = FALSE 29 | EndGlobalSection 30 | EndGlobal 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Microsoft Corporation 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # .NET Portability Analyzer Website 2 | 3 | This repository contains the source code for the [.NET Portability website](http://dotnetstatus.azurewebsites.net/). 4 | 5 | Today, the repository contains the following components: 6 | 7 | * **DotNetStatus**. An ASP.NET 5 implementation of .NET Portability site. 8 | 9 | ## Using this Repository 10 | 11 | 1. Install the following: 12 | 1. [Visual Studio 2015](http://www.visualstudio.com/en-us/downloads/visual-studio-2015-downloads-vs.aspx) 13 | 1. [.NET Version Manager (DNVM)](https://github.com/aspnet/home#getting-started-with-aspnet-5-and-dnx) 14 | 1. [.NET Execution Environment (DNX)](https://github.com/aspnet/home#running-an-application) 15 | 16 | ### Windows 17 | 18 | #### Building/Running from Commandline 19 | 1. Go to `src\DotNetStatus` 20 | 1. Run command: `dnu restore` 21 | 1. Run command: `dnx . web` 22 | 1. The website should be started on `http://localhost:5000` 23 | 24 | #### Building/Running from Visual Studio 25 | 1. Open `DotNetStatus.sln` 26 | 1. Check that all the Dependencies have loaded (like NPM and Bower) and packages were restored 27 | * Check the `Output window -> Package Manager Log` to make sure that everything was successful 28 | 1. There are two targets you can run/debug with: 29 | * IIS Express 30 | * web - To run on DNX 31 | 32 | These can be found under the `Project Properties -> Debug` or by clicking the drop-down menu on the Debug button in your main toolbar. 33 | 1. You can also change the Target DNX Version (ex. so that it runs on .NET Core) by: 34 | * Go to `Project Properties -> Application` 35 | * Check off "Use specific DNX version" 36 | * Change the Platform from `.NET Framework` to `.NET Core` 37 | 38 | #### Troubleshooting 39 | 1. `dnu restore` outputs: Error: ENOENT, stat 'C:\Users\CurrentUser\AppData\Roaming\npm' 40 | * Execute: `mkdir %APPDATA%\npm` (Command Prompt) or `mkdir $env:AppData\npm` (Powershell) 41 | * Execute: `dnu restore` 42 | 1. `dnu restore` outputs: 'grunt' is not recognized as an internal or external command 43 | * Execute: `npm install -g grunt-cli` 44 | * Execute: `dnu restore` 45 | 46 | ### Linux 47 | 48 | #### Building/Running on Ubuntu 49 | 1. Go to `src/DotNetStatus` 50 | 1. Install npm 51 | * `sudo apt-get update` 52 | * `sudo apt-get install nodejs` 53 | * `sudo apt-get install npm` 54 | 1. Install Grunt globally 55 | * `sudo npm install -g grunt-cli` 56 | 1. `dnu restore` 57 | 1. `cd src/DotNetStatus` 58 | 1. `grunt` 59 | 1. Run the site: `dnx . kestrel` 60 | 61 | #### Troubleshooting 62 | 1. `dnu restore` cannot find Microsoft.Fx.Portability 63 | * Open `~/.config/NuGet/NuGet.config` in a text editor 64 | * Add `` under `` 65 | * Try again 66 | 67 | ## How to Engage, Contribute and Provide Feedback 68 | 69 | Some of the best ways to contribute are to try things out, file bugs, and join in design conversations. 70 | 71 | Want to get more familiar with what's going on in the code? 72 | 73 | * [Pull requests](https://github.com/Microsoft/dotnet-apiweb/pulls): [Open](https://github.com/Microsoft/dotnet-apiweb/pulls?q=is%3Aopen+is%3Apr)/[Closed](https://github.com/Microsoft/dotnet-apiweb/pulls?q=is%3Apr+is%3Aclosed) 74 | 75 | Looking for something to work on? The list of [up-for-grabs issues](https://github.com/Microsoft/dotnet-apiweb/issues?q=is%3Aopen+is%3Aissue) is a great place to start. 76 | 77 | We're re-using the same contributing approach as .NET Core. You can check out the .NET Core [contributing guide][Contributing Guide] at the corefx repo wiki for more details. 78 | 79 | * [How to Contribute][Contributing Guide] 80 | * [Contributing Guide][Contributing Guide] 81 | * [Developer Guide] 82 | 83 | You are also encouraged to start a discussion on the .NET Foundation forums! 84 | 85 | [Contributing Guide]: https://github.com/dotnet/corefx/wiki/Contributing 86 | [Developer Guide]: https://github.com/dotnet/corefx/wiki/Developer-Guide 87 | 88 | ## Related Projects 89 | 90 | For an overview of all the .NET related projects, have a look at the 91 | [.NET home repository](https://github.com/Microsoft/dotnet). 92 | 93 | ## License 94 | 95 | This project is licensed under the [MIT license](LICENSE). 96 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "projects": [ "src" ], 3 | "sdk": { 4 | "version": "1.0.0-preview2-003131", 5 | "runtime": "coreclr", 6 | "architecture": "x86" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/DotNetStatus/ApplicationInsights.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 1d7e09ed-05de-4699-97a4-2edbfdb0e139 28 | -------------------------------------------------------------------------------- /src/DotNetStatus/Controllers/DataController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.AspNetCore.Mvc.Rendering; 6 | using Microsoft.Fx.Portability; 7 | using Microsoft.Fx.Portability.ObjectModel; 8 | using System.Collections.Generic; 9 | using System.Threading.Tasks; 10 | 11 | namespace DotNetStatus.Controllers 12 | { 13 | [Route("Data")] 14 | public class DataController : Controller 15 | { 16 | private readonly PortabilityToolsStatusService _portabilityToolsStatusService; 17 | private readonly IEnumerable ListOfDataChoices = new List 18 | { 19 | new SelectListItem() { Text = "Analyzers", Value="Analyzers" }, 20 | new SelectListItem() { Text = "Analyzers summary", Value="AnalyzersSummary" }, 21 | new SelectListItem() { Text = "ApiPort summary", Value="ApiPortSummary" }, 22 | new SelectListItem() { Text = "Breaking changes", Value="BreakingChanges" }, 23 | new SelectListItem() { Text = "Covered by all", Value = "CoveredByAll" }, 24 | new SelectListItem() { Text = "Not covered by any", Value="NotCoveredByAny" }, 25 | new SelectListItem() { Text = "Roll-Up", Value="RollUp", Selected = true } 26 | }; 27 | 28 | public DataController(PortabilityToolsStatusService portabilityToolsStatusService) 29 | { 30 | _portabilityToolsStatusService = portabilityToolsStatusService; 31 | } 32 | 33 | [Route("")] 34 | public IActionResult Index() 35 | { 36 | return View("Index", ListOfDataChoices); 37 | } 38 | 39 | [Route("Analyzers")] 40 | public async Task GetAnalyzersAsync() 41 | { 42 | string query = "/Api/data/Analyzers"; 43 | var data = await _portabilityToolsStatusService.GetJsonDataAsync>(query); 44 | 45 | return PartialView("Analyzers", await _portabilityToolsStatusService.GetAnalyzersAsync()); 46 | } 47 | 48 | [Route("BreakingChanges")] 49 | public async Task GetBreakingChangesAsync() 50 | { 51 | string query = "/Api/data/BreakingChanges"; 52 | var data = await _portabilityToolsStatusService.GetJsonDataAsync>(query); 53 | 54 | return PartialView("BreakingChanges", await _portabilityToolsStatusService.GetBreakingChangesAsync()); 55 | } 56 | 57 | [Route("ApiPortSummary")] 58 | public async Task GetApiPortSummaryAsync() 59 | { 60 | return PartialView("KeyValuePair", await _portabilityToolsStatusService.GetApiPortSummaryAsync()); 61 | } 62 | 63 | [Route("AnalyzersSummary")] 64 | public async Task GetAnalyzersSummaryAsync() 65 | { 66 | return PartialView("KeyValuePair", await _portabilityToolsStatusService.GetAnalyzersSummaryAsync()); 67 | } 68 | 69 | [Route("NotCoveredByAny")] 70 | public async Task GetNotCoveredByAnyAsync() 71 | { 72 | return PartialView("BreakingChanges", await _portabilityToolsStatusService.GetNotCoveredByAnyAsync()); 73 | } 74 | 75 | [Route("CoveredByAll")] 76 | public async Task GetCoveredByAllAsync() 77 | { 78 | return PartialView("BreakingChanges", await _portabilityToolsStatusService.GetCoveredByAllAsync()); 79 | } 80 | 81 | [Route("RollUp")] 82 | public async Task GetRollUpAsync() 83 | { 84 | return PartialView("RollUp", await _portabilityToolsStatusService.GetRollUpAsync()); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /src/DotNetStatus/Controllers/FxApiController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Fx.Portability; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Diagnostics; 9 | using System.Linq; 10 | using System.Threading.Tasks; 11 | 12 | namespace DotNetStatus.Controllers 13 | { 14 | public class FxApiController : Controller 15 | { 16 | private readonly IApiPortService _service; 17 | 18 | public FxApiController(IApiPortService service) 19 | { 20 | _service = service; 21 | } 22 | 23 | [Route("/fxapi")] 24 | public async Task Index(string docId) 25 | { 26 | if (string.IsNullOrEmpty(docId)) 27 | { 28 | return new NotFoundResult(); 29 | } 30 | 31 | try 32 | { 33 | var result = await _service.GetApiInformationAsync(docId); 34 | 35 | return View(result.Response); 36 | } 37 | catch (Exception e) 38 | { 39 | Trace.WriteLine(e); 40 | return new NotFoundResult(); 41 | } 42 | } 43 | 44 | [Route("search")] 45 | public async Task Search(string term) 46 | { 47 | var result = await SearchAsync(term); 48 | 49 | return Json(result.Response); 50 | } 51 | 52 | [Route("validate")] 53 | public async Task Validate(string query) 54 | { 55 | var result = await SearchAsync(query); 56 | 57 | var api = result.Response.FirstOrDefault(f => string.Equals(f.FullName, query, StringComparison.Ordinal)); 58 | 59 | if (api == null) 60 | { 61 | return new NotFoundResult() as ActionResult; 62 | } 63 | else 64 | { 65 | return Json(api); 66 | } 67 | } 68 | 69 | private Task>> SearchAsync(string query) 70 | { 71 | return _service.SearchFxApiAsync($"\"{query}\""); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/DotNetStatus/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Mvc; 5 | 6 | // For more information on enabling MVC for empty projects, visit http://go.microsoft.com/fwlink/?LinkID=397860 7 | 8 | namespace DotNetStatus.Controllers 9 | { 10 | public class HomeController : Controller 11 | { 12 | [Route("")] 13 | public IActionResult Index() 14 | { 15 | return View(); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/DotNetStatus/Controllers/SubmissionController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Fx.Portability; 6 | using Microsoft.Fx.Portability.ObjectModel; 7 | using System.Threading.Tasks; 8 | 9 | namespace DotNetStatus.Controllers 10 | { 11 | public class SubmissionController : Controller 12 | { 13 | private readonly IApiPortService _apiPortService; 14 | 15 | public SubmissionController(IApiPortService apiPortService) 16 | { 17 | _apiPortService = apiPortService; 18 | } 19 | 20 | [Route("Find")] 21 | public ActionResult Find(string id) 22 | { 23 | return RedirectToAction("Index", new { id = id }); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/DotNetStatus/Controllers/UsageController.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Mvc; 5 | using Microsoft.Fx.Portability; 6 | using Microsoft.Fx.Portability.ObjectModel; 7 | using System.Collections.Generic; 8 | using System.Threading.Tasks; 9 | 10 | namespace DotNetStatus.Controllers 11 | { 12 | public class UsageController : Controller 13 | { 14 | private readonly IApiPortService _apiPortService; 15 | 16 | public UsageController(IApiPortService apiPortService) 17 | { 18 | _apiPortService = apiPortService; 19 | } 20 | 21 | [Route("usage")] 22 | public async Task Index(int? skip, int? top, UsageDataFilter? filter, IEnumerable targets) 23 | { 24 | try 25 | { 26 | var usage = await _apiPortService.GetUsageDataAsync(skip ?? 0, top ?? 25, filter ?? UsageDataFilter.HideSupported, targets); 27 | 28 | return View(usage.Response); 29 | } 30 | catch (PortabilityAnalyzerException) 31 | { 32 | return View(null); 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/DotNetStatus/DotNetStatus.xproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 14.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | 7 | 8 | 156e5ab6-c13d-4d12-ad10-2afa192db3b5 9 | DotNetStatus 10 | ..\..\artifacts\obj\$(MSBuildProjectName) 11 | .\bin\ 12 | 13 | 14 | DotNetStatus.vNext 15 | 16 | 17 | 2.0 18 | 62700 19 | 20 | 21 | True 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/DotNetStatus/JSLintNet.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.4", 3 | "ignore": [], 4 | "options": { 5 | "for": true 6 | }, 7 | "globalVariables": [ 8 | "$" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/DotNetStatus/Microsoft.Fx.Portability.ObjectModel/BreakingChangeAnalyzerStatusChartColors.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Microsoft.Fx.Portability.ObjectModel 4 | { 5 | public static class BreakingChangeAnalyzerStatusChartColors 6 | { 7 | public static string GetColor(BreakingChangeAnalyzerStatus breakingChangeAnalyzerStatus) 8 | { 9 | switch (breakingChangeAnalyzerStatus) 10 | { 11 | case BreakingChangeAnalyzerStatus.Available: 12 | return "#e2efda"; 13 | case BreakingChangeAnalyzerStatus.Investigating: 14 | return "#ff6a00"; 15 | case BreakingChangeAnalyzerStatus.NotPlanned: 16 | return "#f8cbad"; 17 | case BreakingChangeAnalyzerStatus.Planned: 18 | return "#fff2cc"; 19 | case BreakingChangeAnalyzerStatus.Unknown: 20 | return "#808080"; 21 | default: 22 | throw new ArgumentOutOfRangeException( 23 | $"BreakingChangeAnalyzerStatusChartColors_GetColor: {breakingChangeAnalyzerStatus.ToString()} is not defined as a color!"); 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/DotNetStatus/Microsoft.Fx.Portability.ObjectModel/ChartJSDataItem.cs: -------------------------------------------------------------------------------- 1 | namespace Microsoft.Fx.Portability.ObjectModel 2 | { 3 | public class ChartJSStackedBarDataItem 4 | { 5 | public BreakingChangeAnalyzerStatus label { get; set; } 6 | public string backgroundColor { get; set; } 7 | public int[] data { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/DotNetStatus/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Hosting; 7 | 8 | namespace DotNetStatus 9 | { 10 | public class Program 11 | { 12 | public static void Main(string[] args) 13 | { 14 | var host = new WebHostBuilder() 15 | .UseKestrel() 16 | .UseContentRoot(Directory.GetCurrentDirectory()) 17 | .UseIISIntegration() 18 | .UseStartup() 19 | .Build(); 20 | 21 | host.Run(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/DotNetStatus/Properties/debugSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Profiles": [] 3 | } -------------------------------------------------------------------------------- /src/DotNetStatus/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:28521/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "Hosting:Environment": "Development" 16 | }, 17 | "sdkVersion": "dnx-coreclr-win-x86.1.0.0-rc1-update1" 18 | }, 19 | "web": { 20 | "commandName": "web", 21 | "environmentVariables": { 22 | "Hosting:Environment": "Development" 23 | } 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/DotNetStatus/Services/PortabilityToolsStatusService.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.Fx.Portability.ObjectModel; 5 | using Newtonsoft.Json; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Net.Http; 10 | using System.Threading.Tasks; 11 | 12 | namespace Microsoft.Fx.Portability 13 | { 14 | public class PortabilityToolsStatusService 15 | { 16 | private readonly HttpClient _client; 17 | 18 | public PortabilityToolsStatusService(HttpClient client, ProductInformation productInfo) 19 | { 20 | _client = client; 21 | } 22 | 23 | /// 24 | /// Returns Json from the WebAPI calls made to the APIPortService 25 | /// 26 | /// the webapi action to run 27 | public async Task GetJsonDataAsync(string query) 28 | { 29 | using (var response = await _client.GetAsync(CreateFullUrl(query))) 30 | { 31 | if (!response.IsSuccessStatusCode) 32 | { 33 | return default(T); 34 | } 35 | 36 | var content = await response.Content.ReadAsStringAsync(); 37 | var result = JsonConvert.DeserializeObject(content, DataExtensions.JsonSettings); 38 | return result; 39 | } 40 | } 41 | 42 | /// 43 | /// Creates the full URL for the query to be processed by putting the ApiPort Url together with the query 44 | /// 45 | /// the apiportservice webapi action to be combined with the apiport URL 46 | private Uri CreateFullUrl(string query) 47 | { 48 | var result = new Uri(_client.BaseAddress, query); 49 | return result; 50 | } 51 | 52 | public async Task> GetAnalyzersAsync() 53 | { 54 | string query = "/Api/data/Analyzers"; 55 | var data = await GetJsonDataAsync>(query); 56 | 57 | return data.OrderBy(o => o.GetIdNumber()); 58 | } 59 | 60 | public async Task> GetBreakingChangesAsync() 61 | { 62 | string query = "/Api/data/BreakingChanges"; 63 | var data = await GetJsonDataAsync>(query); 64 | 65 | return SortBreakingChanges(data); 66 | } 67 | 68 | public async Task>> GetApiPortSummaryAsync() 69 | { 70 | string query = "/Api/toolsData/ApiPort/Summary"; 71 | var data = await GetJsonDataAsync>>(query); 72 | 73 | return data.OrderByDescending(o => o.Value); 74 | } 75 | 76 | public async Task>> GetAnalyzersSummaryAsync() 77 | { 78 | string query = "/Api/toolsData/Analyzers/Summary"; 79 | var data = await GetJsonDataAsync>>(query); 80 | 81 | return data.OrderByDescending(o => o.Value); 82 | } 83 | 84 | public async Task> GetNotCoveredByAnyAsync() 85 | { 86 | string query = "/Api/toolsData/Coverage/None"; 87 | return SortBreakingChanges(await GetJsonDataAsync>(query)); 88 | } 89 | 90 | public async Task> GetCoveredByAllAsync() 91 | { 92 | string query = "/Api/toolsData/Coverage/CoveredByAll"; 93 | return SortBreakingChanges(await GetJsonDataAsync>(query)); 94 | } 95 | 96 | public async Task>>>> GetRollUpAsync() 97 | { 98 | var result = new List>>> 99 | { 100 | BuildRollUpEnumerable("ApiPort Status", await GetApiPortSummaryAsync()), 101 | BuildRollUpEnumerable("Analyzers Status", await GetAnalyzersSummaryAsync()), 102 | BuildRollUpEnumerable("Covered By All", BuildRollUpKeyValuePair(BreakingChangeAnalyzerStatus.Available, (await GetCoveredByAllAsync()).Count())), 103 | BuildRollUpEnumerable("Not Covered By Any", BuildRollUpKeyValuePair(BreakingChangeAnalyzerStatus.NotPlanned, (await GetNotCoveredByAnyAsync()).Count())) 104 | }; 105 | 106 | return result; 107 | } 108 | 109 | private KeyValuePair>> BuildRollUpEnumerable(string key, IEnumerable> value) 110 | { 111 | return new KeyValuePair>>(key, value); 112 | } 113 | 114 | private IEnumerable> BuildRollUpKeyValuePair(BreakingChangeAnalyzerStatus breakingChangeAnalyzerStatus, int value) 115 | { 116 | return new List> 117 | { 118 | new KeyValuePair(breakingChangeAnalyzerStatus, value) 119 | }; 120 | } 121 | 122 | private IEnumerable SortBreakingChanges(IEnumerable enumToSort) 123 | { 124 | int id; 125 | return (enumToSort.OrderBy(o => int.TryParse(o.Id, out id) ? id : int.MaxValue)); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/DotNetStatus/Startup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.Extensions.Configuration; 7 | using Microsoft.Extensions.DependencyInjection; 8 | using Microsoft.Extensions.Logging; 9 | using Microsoft.Fx.Portability; 10 | using System; 11 | using System.Net.Http; 12 | 13 | namespace DotNetStatus 14 | { 15 | public class Startup 16 | { 17 | private readonly IConfiguration _configuration; 18 | 19 | public Startup(IHostingEnvironment env) 20 | { 21 | // Setup configuration sources. 22 | var builder = new ConfigurationBuilder() 23 | .AddJsonFile(env.ContentRootFileProvider, "appsettings.json", false, true) 24 | .AddJsonFile(env.ContentRootFileProvider, $"appsettings.{env.EnvironmentName}.json", true, true) 25 | .AddEnvironmentVariables(); 26 | 27 | _configuration = builder.Build(); 28 | } 29 | 30 | public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 31 | { 32 | loggerFactory.AddConsole(); 33 | 34 | // Add the following to the request pipeline only in development environment. 35 | if (env.IsDevelopment()) 36 | { 37 | app.UseBrowserLink(); 38 | app.UseDeveloperExceptionPage(); 39 | } 40 | else 41 | { 42 | // Add Error handling middleware which catches all application specific errors and 43 | // send the request to the following path or controller action. 44 | app.UseExceptionHandler("/Home/Error"); 45 | } 46 | 47 | // Add static files to the request pipeline 48 | app.UseStaticFiles(); 49 | 50 | // Add MVC to the request pipeline (we use attribute routing) 51 | app.UseMvc(); 52 | } 53 | 54 | public void ConfigureServices(IServiceCollection services) 55 | { 56 | services.AddSingleton(new ProductInformation("DotNetStatus")); 57 | services.AddSingleton(CreateService); 58 | services.AddSingleton(CreateJsonDataService); 59 | 60 | // Add MVC services to container 61 | services.AddMvc(); 62 | services.AddLogging(); 63 | } 64 | 65 | private IApiPortService CreateService(IServiceProvider arg) 66 | { 67 | return new ApiPortService(GetApiPortUrl(), arg.GetRequiredService()); 68 | } 69 | 70 | private PortabilityToolsStatusService CreateJsonDataService(IServiceProvider arg) 71 | { 72 | return new PortabilityToolsStatusService(CreateHttpClient(), arg.GetRequiredService()); 73 | } 74 | 75 | /// 76 | /// Get's the URL from ApiPort setting in appsettings.json 77 | /// 78 | private string GetApiPortUrl() 79 | { 80 | string endpoint = _configuration["ApiPortService:Url"]; 81 | if (string.IsNullOrEmpty(endpoint)) 82 | { 83 | throw new ArgumentNullException("ApiPortService", "Need to specify ApiPortService in appsettings.json"); 84 | } 85 | 86 | return endpoint; 87 | } 88 | 89 | /// 90 | /// Creates an HTTPClient with the appsettings.json Url 91 | /// 92 | private HttpClient CreateHttpClient() 93 | { 94 | var client = new HttpClient(); 95 | 96 | client.BaseAddress = new Uri(GetApiPortUrl()); 97 | client.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "application/json"); 98 | client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json"); 99 | client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "AnalyzerStatusCheck"); 100 | 101 | return client; 102 | } 103 | 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Data/Analyzers.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @using Microsoft.Fx.Portability.ObjectModel 6 | @model IEnumerable 7 | 8 | 9 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | @foreach (var item in Model) 22 | { 23 | 24 | 27 | 30 | 31 | } 32 | 33 |
12 | Id 13 | 15 | Name 16 |
25 | @Html.DisplayFor(modelItem => item.IdNumber) 26 | 28 | @Html.DisplayFor(modelItem => item.AnalyzerName) 29 |
34 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Data/BreakingChanges.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @using Microsoft.Fx.Portability 6 | @model IEnumerable 7 | 8 | 9 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | @foreach (var item in Model) 22 | { 23 | 24 | 27 | 30 | 31 | } 32 | 33 |
12 | Id 13 | 15 | Title 16 |
25 | @Html.DisplayFor(modelItem => item.Id) 26 | 28 | @Html.DisplayFor(modelItem => item.Title) 29 |
34 | 35 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Data/Index.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @model IEnumerable 6 | 7 | @{ 8 | ViewBag.Title = "Tools Coverage"; 9 | } 10 | 11 |
12 |

.NET Compatibility Diagnostic Tools Coverage

13 | @Html.Label("Available Data:") 14 | @Html.DropDownList("AvailableChoices", Model) 15 |
16 | 17 |
18 |
19 | 20 | 29 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Data/KeyValuePair.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @using Microsoft.Fx.Portability; 6 | @using Microsoft.Fx.Portability.ObjectModel; 7 | @using Newtonsoft.Json; 8 | @using Newtonsoft.Json.Converters; 9 | @using System.Linq; 10 | @using System.Text; 11 | 12 | @model IEnumerable> 13 | 14 | @{ 15 | var data = @Html.Raw(JsonConvert.SerializeObject(Model.Select(v => v.Value), new StringEnumConverter())); 16 | var colors = @Html.Raw(JsonConvert.SerializeObject(Model.Select(v => BreakingChangeAnalyzerStatusChartColors.GetColor(v.Key)), new StringEnumConverter())); 17 | var labels = @Html.Raw(JsonConvert.SerializeObject(Model.Select(v => v.Key), new StringEnumConverter())); 18 | } 19 | 20 | @functions{ 21 | private string CreateLegend() 22 | { 23 | //Create string builder with starting div 24 | StringBuilder result = new StringBuilder("\"
"); 25 | 26 | //add legend items 27 | foreach (var key in Model.Select(v => v.Key)) 28 | { 29 | result.Append($"{key.ToString()}"); 30 | } 31 | 32 | //add ending div 33 | result.Append("
\""); 34 | 35 | return result.ToString(); 36 | } 37 | } 38 | 39 |
40 | 41 | 42 | 77 | 81 | 82 |
43 | 44 | 45 | 46 | 49 | 52 | 53 | 54 | 55 | 56 | @foreach (var item in Model) 57 | { 58 | 59 | 62 | 65 | 66 | } 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 |
47 | Name 48 | 50 | Value 51 |
60 | @Html.DisplayFor(modelItem => item.Key) 61 | 63 | @Html.DisplayFor(modelItem => item.Value) 64 |
76 |
78 | 79 | 80 |
83 |
84 | 85 | 86 | 93 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Data/RollUp.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @using Microsoft.Fx.Portability; 6 | @using Microsoft.Fx.Portability.ObjectModel; 7 | @using Newtonsoft.Json; 8 | @using Newtonsoft.Json.Converters; 9 | @using System.Collections.Generic; 10 | @using System.Linq; 11 | @using System.Text; 12 | 13 | @model IEnumerable>>> 14 | 15 | @{ 16 | //Get the enumerables from the model that have more then one item 17 | var multipleValueEnumerables = Model.Where(o => o.Value.Count() > 1); 18 | 19 | //Get the enumerables from the model that have only one item 20 | var singleValueEnumerables = Model.Where(o => o.Value.Count() == 1); 21 | 22 | //get the ChartJS chart information 23 | var uniqueAnalyzerStatusLabels = GetUniqueAnalyzerStatusLabels(Model); 24 | var dataSets = @Html.Raw(JsonConvert.SerializeObject(GetChartDataItems(uniqueAnalyzerStatusLabels, Model), new StringEnumConverter())); 25 | var labels = @Html.Raw(JsonConvert.SerializeObject(Model.Select(v => v.Key), new StringEnumConverter())); 26 | } 27 | 28 | 29 |
30 | 31 | 32 | 95 | 99 | 100 |
33 |
34 | @foreach (var summary in multipleValueEnumerables) 35 | { 36 |

@summary.Key.ToString()

37 | 38 | 39 | 40 | @foreach (var columnHeader in summary.Value) 41 | { 42 | 45 | } 46 | 49 | 50 | 51 | 52 | 53 | 54 | @foreach (var item in summary.Value) 55 | { 56 | 59 | } 60 | 63 | 64 | 65 |
43 | @Html.Label(columnHeader.Key.ToString()) 44 | 47 | Total 48 |
57 | @Html.DisplayFor(modelItem => item.Value) 58 | 61 | @summary.Value.Sum(v => v.Value) 62 |
66 | } 67 |
68 |
69 |

Other

70 | 71 | 72 | 73 | 76 | 79 | 80 | 81 | 82 | @foreach (var summary in singleValueEnumerables) 83 | { 84 | 85 | 86 | 89 | 90 | } 91 | 92 |
74 | Name 75 | 77 | value 78 |
@summary.Key.ToString() 87 | @summary.Value.First().Value 88 |
93 |
94 |
96 | 97 | 98 |
101 |
102 | 103 | 104 | 111 | 112 | @functions { 113 | /// 114 | /// Returns a list of chart items 115 | /// 116 | /// List of BreakingChangeAnalyzerStatus 117 | /// PortabilityTools roll up summary 118 | private IEnumerable GetChartDataItems( 119 | IEnumerable analyzerStatusLabels, 120 | IEnumerable>>> rollUp) 121 | { 122 | var result = new List(); 123 | 124 | foreach (var uniqueAnalyzerStatusLabel in analyzerStatusLabels) 125 | { 126 | result.Add(new ChartJSStackedBarDataItem 127 | { 128 | label = uniqueAnalyzerStatusLabel, 129 | backgroundColor = BreakingChangeAnalyzerStatusChartColors.GetColor(uniqueAnalyzerStatusLabel), 130 | data = GetAnalyzerStatusLabelDataValues(uniqueAnalyzerStatusLabel, rollUp) 131 | }); 132 | } 133 | 134 | return result; 135 | } 136 | 137 | /// 138 | /// Returns a list of unique BreakingChangeAnalyzerStatus from the rollUp summary 139 | /// 140 | /// PortabilityTools roll up summary 141 | private IEnumerable GetUniqueAnalyzerStatusLabels( 142 | IEnumerable>>> rollUp) 143 | { 144 | return rollUp.SelectMany(s => s.Value).Select(k => k.Key).Distinct().ToList(); 145 | } 146 | 147 | /// 148 | /// Returns a list of chart items 149 | /// 150 | /// BreakingChangeAnalyzerStatus 151 | /// PortabilityTools roll up summary 152 | private int[] GetAnalyzerStatusLabelDataValues( 153 | BreakingChangeAnalyzerStatus analyzerStatusLabel, 154 | IEnumerable>>> rollUp) 155 | { 156 | var result = new List(); 157 | 158 | foreach (var rollUpItem in rollUp) 159 | { 160 | var item = rollUpItem.Value.Where(b => b.Key.Equals(analyzerStatusLabel)); 161 | result.Add((item.Count() != 0) ? item.First().Value : 0); 162 | } 163 | 164 | return result.ToArray(); 165 | } 166 | 167 | private string CreateLegend() 168 | { 169 | //Create string builder with starting div 170 | StringBuilder result = new StringBuilder("\"
"); 171 | 172 | //add legend items 173 | foreach (var uniqueAnalyzerStatusLabel in GetUniqueAnalyzerStatusLabels(Model)) 174 | { 175 | result.Append($"{uniqueAnalyzerStatusLabel.ToString()}"); 176 | } 177 | 178 | //add ending div 179 | result.Append("
\""); 180 | 181 | return result.ToString(); 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/FxApi/Index.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @model Microsoft.Fx.Portability.ApiInformation 6 | @using DotNetStatus 7 | 8 | @{ 9 | ViewBag.Title = @Model.Definition.DocId; 10 | } 11 | 12 |
13 |
14 |
15 | 18 |
19 |
20 | 21 | @if (!string.IsNullOrEmpty(Model.RecommendedChanges)) 22 | { 23 | 27 | } 28 | 29 |

Supported on:

30 |
    31 | @foreach (var target in Model.Supported.GroupBy(s => s.Identifier)) 32 | { 33 |
  • 34 | @foreach (var version in target.OrderByDescending(t => t.Version)) 35 | { 36 | @version.Version 37 | } 38 | @target.Key 39 |
  • 40 | } 41 |
42 | 43 | @if (Model.AdditionalInformation.Any()) 44 | { 45 |

Additional information:

46 | foreach (var additional in Model.AdditionalInformation) 47 | { 48 |
49 |
50 |

@additional.Title

51 |
52 | @*
@Html.Markdown(additional.Html)
*@ 53 |
@additional.Markdown
54 |
55 | } 56 | } 57 |
58 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @{ 6 | ViewBag.Title = "Diagnostic Tools"; 7 | } 8 | 9 |
10 |

.NET Compatibility Diagnostic Tools

11 |
12 |
13 |
14 |

15 | This site provides information about the available compatibility diagnostic tools. These tools are helpful in identifying potential 16 | .NET Framework Compatibility 17 | issues when moving from one .NET Framework version to another. Below are the links to the tools. 18 |

19 |

20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
ToolDownload location
Console ApplicationGitHub Releases
VS PluginThe Visual Studio Gallery
38 |

39 |

40 | If you want to learn more about these tools, you should check out this Channel 9 video: 41 |

42 |

43 | 44 |

45 |
46 |
47 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @{ 6 | Layout = null; 7 | } 8 | 9 | 10 | 11 | 12 | 13 | Error 14 | 15 | 16 |
17 |

Error.

18 |

An error occurred while processing your request.

19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | @ViewBag.Title 12 | 13 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | @RenderSection("scripts", required: false) 42 | 43 | 44 | 45 | 74 |
75 | @RenderBody() 76 |
77 |
78 |

79 | Copyright (c) 2016 Microsoft Corporation. All rights reserved. 80 | Terms 81 | Contact 82 |

83 |
84 |
85 | 86 | 87 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Submission/Index.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @using Microsoft.Fx.Portability; 6 | @using Microsoft.Fx.Portability.ObjectModel; 7 | 8 | @{ 9 | ViewBag.Title = "View Submission Result"; 10 | 11 | var exception = Model as PortabilityAnalyzerException; 12 | var m = Model as AnalyzeResponse; 13 | } 14 | 15 | @if (exception != null) 16 | { 17 | @Html.Partial("_Find", exception) 18 | } 19 | else if (m != null && Model.Targets == null) 20 | { 21 | @Html.Partial("_Find", m) 22 | } 23 | else if (m != null) 24 | { 25 |
26 |

View result for @m.SubmissionId

27 |
28 |
29 | @Html.Partial("_SubmissionResult", m) 30 |
31 | } 32 | else 33 | { 34 | @Html.Partial("_Find") 35 | } 36 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Submission/_Find.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @using Microsoft.Fx.Portability; 6 | @using Microsoft.Fx.Portability.ObjectModel; 7 | 8 | @{ 9 | ViewBag.Title = "Find"; 10 | } 11 | 12 |
13 |
14 |

Please enter a submission id

15 |
16 |
17 | @if (Model is AnalyzeResponse) 18 | { 19 | var submissionId = (Model as AnalyzeResponse).SubmissionId; 20 | 21 | 25 | } 26 | else if (Model is PortabilityAnalyzerException) 27 | { 28 | 33 | } 34 | 35 |
36 |
37 |
38 | 39 | 40 |
41 | 42 | 43 |
44 |
45 |
46 |
47 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Submission/_SubmissionResult.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @model Microsoft.Fx.Portability.ObjectModel.AnalyzeResponse 6 | 7 | @if (Model.MissingDependencies.Any()) 8 | { 9 |
10 | @{ 11 | var count = 0; 12 | var panelGroupName = "assemblyPanelGroup"; 13 | var grouped = Model.MissingDependencies.GroupBy(a => a.TypeDocId).OrderBy(a => a.Key).Where(a => !string.IsNullOrEmpty(a.Key)); 14 | } 15 | 16 | @if (grouped.Any()) 17 | { 18 |
19 | @foreach (var item in grouped) 20 | { 21 | var panelName = string.Format("assemblyPanel{0}", count++); 22 | 23 |
24 | 29 |
30 |
31 | 32 | 33 | 34 | @foreach (var target in Model.Targets) 35 | { 36 | 37 | } 38 | 39 | @foreach (var value in item) 40 | { 41 | 42 | 43 | @for (var i = 0; i < Model.Targets.Count; i++) 44 | { 45 | var supportedTarget = value.TargetStatus[i]; 46 | var actualTarget = Model.Targets[i].Version; 47 | 48 | if (supportedTarget == null || actualTarget < supportedTarget) 49 | { 50 | 51 | } 52 | else 53 | { 54 | 55 | } 56 | } 57 | 58 | } 59 |
API@target
@value
60 |
61 |
62 |
63 | } 64 |
65 | } 66 | else 67 | { 68 |
69 | @{ 70 | var panelName = string.Format("assemblyPanel{0}", count++); 71 | } 72 | 73 |
74 | 79 |
80 |
81 | 82 | 83 | 84 | @foreach (var target in Model.Targets) 85 | { 86 | 87 | } 88 | 89 | @foreach (var item in Model.MissingDependencies) 90 | { 91 | 92 | 93 | @for (var i = 0; i < Model.Targets.Count; i++) 94 | { 95 | var supportedTarget = item.TargetStatus[i]; 96 | var actualTarget = Model.Targets[i].Version; 97 | 98 | if (supportedTarget == null || actualTarget < supportedTarget) 99 | { 100 | 101 | } 102 | else 103 | { 104 | 105 | } 106 | } 107 | 108 | } 109 |
Type Name@target
@item.MemberDocId
110 |
111 |
112 |
113 |
114 | } 115 |
116 | } 117 | else 118 | { 119 |
120 |

You are good to go for the following platforms

121 |
    122 | @foreach (var target in Model.Targets) 123 | { 124 |
  • @target
  • 125 | } 126 |
127 |
128 | } 129 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Usage/Index.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @model Microsoft.Fx.Portability.ObjectModel.UsageDataCollection 6 | 7 | @{ 8 | ViewBag.Title = "API Usage"; 9 | } 10 | 11 |
12 |

.NET Framework API usage data from the .NET Portability Analyzer tool

13 |
14 | 15 |
16 | @await Html.PartialAsync("_Usage", Model) 17 |
18 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Usage/_Error.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Usage/_Legend.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | 6 |
7 |
8 | This data is a summary of the data we have collected from ApiPort (console and VS extension) submissions. This data is from @Model.SubmissionCount.ToString("N0") submissions. 9 |
10 |
11 |
12 |
13 |
14 | 15 | 16 | 17 | 20 | 21 | 22 | 25 | 26 |
18 | Supported API 19 |
23 | This API is supported on the target 24 |
27 |
28 |
29 | 30 | 31 | 32 | 35 | 36 | 37 | 40 | 41 |
33 | Not supported API 34 |
38 | The API is not supported on the target. It may, however, be available via NuGet 39 |
42 |
43 |
44 |
45 |
46 | 47 | 48 | 55 | 58 | 59 | 60 | 63 | 64 |
49 |
50 | 51 | R 52 | 53 |
54 |
56 | Recommended changes 57 |
61 | These changes help your code be the most portable 62 |
65 |
66 |
67 | 68 | 69 | 76 | 79 | 80 | 81 | 84 | 85 |
70 |
71 | 72 | S 73 | 74 |
75 |
77 | Source compatible 78 |
82 | The API used is not available, but there are equivalents that the compiler will use. 83 |
86 |
87 |
88 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Usage/_Usage.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @model Microsoft.Fx.Portability.ObjectModel.UsageDataCollection 6 | 7 | @if (Model == null) 8 | { 9 | @Html.Partial("_Error") 10 | } 11 | else 12 | { 13 | @Html.Partial("_UsageGrid", Model) 14 | } 15 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/Usage/_UsageGrid.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @model Microsoft.Fx.Portability.ObjectModel.UsageDataCollection 6 | 7 | @using Microsoft.Fx.Portability.ObjectModel; 8 | 9 | @{ 10 | var numberInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.Clone() as System.Globalization.NumberFormatInfo; 11 | numberInfo.PercentPositivePattern = 1; 12 | 13 | const string UpdateButtonJS = "$('#updateBtn').click()"; 14 | 15 | var topSelectionListItems = new SortedSet(new[] { 25, 50, 100, 150, 250, Model.Top }) 16 | .Select(top => new SelectListItem 17 | { 18 | Text = top.ToString(), 19 | Value = top.ToString(), 20 | Selected = Model.Top == top 21 | }); 22 | 23 | var filters = new[] 24 | { 25 | new { Filter = UsageDataFilter.HideSupported, Description = "APIs that lack support on some platforms" }, 26 | new { Filter = UsageDataFilter.ShowAll, Description = "All APIs" } 27 | }; 28 | 29 | var hideSupportedSelectionListItems = filters 30 | .OrderBy(f => f.Description) 31 | .Select(f => new SelectListItem { Text = f.Description, Value = f.Filter.ToString(), Selected = Model.Filter == f.Filter }); 32 | } 33 | 34 |
35 |
36 | 37 | @using (Html.BeginForm()) 38 | { 39 | @Html.Hidden("skip", Model.Skip) 40 |
41 |
42 |
43 |
44 |

Customize View

45 |
46 |
47 |
48 |
49 |
50 | 51 | @Html.DropDownList("top", topSelectionListItems, new { @class = "form-control", onchange = UpdateButtonJS }) 52 |
53 | 54 |
55 | 56 | @Html.DropDownList("filter", hideSupportedSelectionListItems, new { @class = "form-control", onchange = UpdateButtonJS }) 57 |
58 |
59 | 60 | 61 | 62 |
63 |
64 | @foreach (var target in Model.AllTargets.OrderBy(t => t.Identifier)) 65 | { 66 |
67 | 70 |
71 | } 72 |
73 |
74 | 75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |

Legend

83 |
84 |
85 | @Html.Partial("_Legend") 86 |
87 |
88 |
89 |
90 |
91 | 92 | 93 | 94 | 95 | 96 | @foreach (var framework in Model.Targets) 97 | { 98 | 99 | } 100 | 101 | 102 | @foreach (var item in Model.Usage) 103 | { 104 | var percentageUsed = (float)item.Count / (float)Model.SubmissionCount; 105 | 106 | 107 | 108 | 109 | 110 | 111 | @if (!string.IsNullOrWhiteSpace(item.Api.RecommendedChanges)) 112 | { 113 | 118 | } 119 | else 120 | { 121 | 122 | } 123 | 124 | @if (!string.IsNullOrWhiteSpace(item.Api.SourceCompatibleChanges)) 125 | { 126 | 131 | } 132 | else 133 | { 134 | 135 | } 136 | 137 | @foreach (var target in Model.Targets) 138 | { 139 | var isSupported = item.Api.Supported.Contains(target); 140 | var tdClass = isSupported ? "IconSuccessEncoded" : "IconErrorEncoded"; 141 | 142 | } 143 | 144 | } 145 |
RankUsageAPI@framework.Identifier
@item.Index@string.Format(numberInfo, "{0:P0}", percentageUsed)@Html.ActionLink(@item.Api.Definition.FullName, "Index", "FxApi", new { docId = @item.Api.Definition.DocId }, null) 114 | 115 | R 116 | 117 | 127 | 128 | S 129 | 130 |
146 |
147 |
148 |
149 |
150 |
151 | @{ 152 | var previousClass = Model.PreviousSkip == -1 ? "disabled='disabled'" : string.Empty; 153 | var nextClass = Model.NextSkip == -1 ? "disabled='disabled'" : string.Empty; 154 | } 155 | 156 | 162 |
163 |
164 | } 165 |
166 |
167 | -------------------------------------------------------------------------------- /src/DotNetStatus/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @addTagHelper "*, Microsoft.AspNetCore.Mvc.TagHelpers" -------------------------------------------------------------------------------- /src/DotNetStatus/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | *@ 4 | 5 | @{ 6 | Layout = "/Views/Shared/_Layout.cshtml"; 7 | } 8 | -------------------------------------------------------------------------------- /src/DotNetStatus/appsettings.development.json: -------------------------------------------------------------------------------- 1 | { 2 | "ApiPortService": { 3 | "Url": "http://Localhost:25451" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/DotNetStatus/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ApiPortService": { 3 | "Url": "https://portability.dot.net" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/DotNetStatus/assets/css/DotNetStatus.css: -------------------------------------------------------------------------------- 1 | /* Copyright (c) Microsoft. All rights reserved. 2 | Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | */ 4 | 5 | .status-table-header { 6 | background-color: #eeeeee 7 | } 8 | 9 | .status-table-footer { 10 | background-color: #eeeeee 11 | } 12 | 13 | .status-cell-alignment { 14 | text-align: center; 15 | vertical-align: middle; 16 | } 17 | 18 | .status-chart-legenditem { 19 | padding: 3px; 20 | border: solid; 21 | border-width: 4px; 22 | margin: 5px; 23 | text-align: center; 24 | } -------------------------------------------------------------------------------- /src/DotNetStatus/assets/css/PopoverStyles.css: -------------------------------------------------------------------------------- 1 | .apiinfo { 2 | color: white; 3 | font-family: Consolas,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New, monospace; 4 | } 5 | 6 | a.apiinfo:link { 7 | color: white; 8 | text-decoration: none; 9 | } 10 | 11 | a.apiinfo:visited { 12 | color: white; 13 | text-decoration: none; 14 | } 15 | 16 | a.apiinfo:hover { 17 | color: lightgray; 18 | text-decoration: none; 19 | } 20 | 21 | a.apiinfo:active { 22 | color: white; 23 | text-decoration: none; 24 | } 25 | 26 | .sourcecompatibility { 27 | background-color: purple; 28 | } 29 | 30 | .recommendedchange { 31 | background-color: mediumpurple; 32 | } 33 | 34 | .legend { 35 | border: hidden; 36 | } 37 | 38 | div.apiinfo.legend, .sourcecompatibility, .recommendedchange { 39 | width: 30px; 40 | height: 30px; 41 | text-align: center; 42 | } 43 | 44 | td.legend-key { 45 | width: 50px; 46 | } 47 | 48 | span.apiinfo.legend { 49 | display: table-cell; 50 | vertical-align: middle; 51 | padding: 0; 52 | } 53 | -------------------------------------------------------------------------------- /src/DotNetStatus/assets/css/navbar.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 20px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | .navbar { 7 | margin-bottom: 20px; 8 | } 9 | 10 | .docId { 11 | font-family: Consolas,monospace; 12 | } 13 | -------------------------------------------------------------------------------- /src/DotNetStatus/assets/css/search.css: -------------------------------------------------------------------------------- 1 | .ui-autocomplete { 2 | /* Need to set z-index high so it will show above the navbar */ 3 | z-index: 100000; 4 | } 5 | 6 | .invalid-query { 7 | background-color: lightcoral; 8 | color: white; 9 | } 10 | -------------------------------------------------------------------------------- /src/DotNetStatus/assets/css/usageicons.css: -------------------------------------------------------------------------------- 1 | .centerHeader { 2 | text-align: center; 3 | } 4 | 5 | /* All Icons */ 6 | .IconSuccessEncoded, .IconInfoEncoded, .IconWarningEncoded, .IconErrorEncoded { 7 | min-width: 18px; 8 | min-height: 18px; 9 | background-repeat: no-repeat; 10 | background-position: center; 11 | } 12 | 13 | /* Success icon encoded */ 14 | .IconSuccessEncoded { 15 | /* Note: Do not delete the comment below. It is used to verify the correctness of the encoded image resource below before the product is released */ 16 | /* [---XsltValidateInternal-Base64EncodedImage:IconSuccess#Begin#background-image: url(data:image/png;base64,#Separator#);#End#] */ 17 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABPElEQVR4Xp1Tv0vDUBi8FqeA4NpBcBLcWnQSApncOnTo4FSnjP0DsnXpH5CxiwbHDg4Zuj4oOEXiJgiC4FDcCkLWmIMc1Pfw+eMgQ77v3Xf3Pe51YKGqqisAEwCR1TIAsiAIblSo6xrdHeJR85Xle3mdmCQKb0PsfqyxxzM8K15HZADl/H5+sHpZwYfxyRjTs+kWwKBx8yoHd2mRiuzF8mkJniWH/13u3Fjrs/EdhsdDFHGB/DLXEJBDLh1MWPAhPo1BLB4WX5yQywHR+m3tVe/t97D52CB/ziG0nIgD/qDuYg8WuCcVZ2YGwlJ3YDugkpR/VNcAEx6GEKhERSr71FuO4YCM4XBdwKvecjIlkSnsO0Hyp/GxSeJAdzBKzpOtnPwyyiPdAZhpZptT04tU+zk7s8czeges//s5C5+CwqrR4/gw+AAAAABJRU5ErkJggg==); 18 | } 19 | 20 | /* Information icon encoded */ 21 | .IconInfoEncoded { 22 | /* Note: Do not delete the comment below. It is used to verify the correctness of the encoded image resource below before the product is released */ 23 | /* [---XsltValidateInternal-Base64EncodedImage:IconInformation#Begin#background-image: url(data:image/png;base64,#Separator#);#End#] */ 24 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHElEQVR4Xs2TsUoDQRRF7wwoziokjZUKadInhdhukR9YP8DMX1hYW+QvdsXa/QHBbcXC7W0CamWTQnclFutceIQJwwaWNLlwm5k5d94M76mmaeCrrmsLYOocY12FcxZFUeozCqKqqgYA8uevv1H6VuPxcwlfk5N92KHBxfFeCSAxxswlYAW/Xr989x/mv9gkhtyMDhcAxgzRsp7flj8B/HF1RsMXq+NZMkopaHe7lbKxQUEIGbKsYNoGn969060hZBkQex/W8oRQwsQaW2o3Ago2SVcJUzAgY3N0lTCZZm+zPS8HB51gMmS1DEYyOz9acKO1D8JWTlafKIMxdhvlfdyT94Vv5h7P8Ky7nQzACmhvKq3zk3PjW9asz9D/1oigecsioooAAAAASUVORK5CYII=); 25 | } 26 | 27 | /* Warning icon encoded */ 28 | .IconWarningEncoded { 29 | /* Note: Do not delete the comment below. It is used to verify the correctness of the encoded image resource below before the product is released */ 30 | /* [---XsltValidateInternal-Base64EncodedImage:IconWarning#Begin#background-image: url(data:image/png;base64,#Separator#);#End#] */ 31 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAx0lEQVR4XpWSMQ7CMAxFf4xAyBMLCxMrO8dhaBcuwdCJS3RJBw7SA/QGTCxdWJgiQYWKXJWKIXHIlyw5lqr34tQgEOdcBsCOx5yZK3hCCKdYXneQkh4pEfqzLfu+wVDSyyzFoJjfz9NB+pAF+eizx2Vruts0k15mPgvS6GYvpVtQhB61IB/dk6AF6fS4Ben0uIX5odtFe8Q/eW1KvFeH4e8khT6+gm5B+t3juyDt7n0jpe+CANTd+oTUjN/U3yVaABnSUjFz/gFq44JaVSCXeQAAAABJRU5ErkJggg==); 32 | } 33 | 34 | /* Error icon encoded */ 35 | .IconErrorEncoded { 36 | /* Note: Do not delete the comment below. It is used to verify the correctness of the encoded image resource below before the product is released */ 37 | /* [---XsltValidateInternal-Base64EncodedImage:IconError#Begin#background-image: url(data:image/png;base64,#Separator#);#End#] */ 38 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABQElEQVR4XqWTvUoEQRCE6wYPZUA80AfwAQz23uCMjA7MDRQEIzPBVEyNTQUFIw00vcQTTMzuAh/AxEQQT8HF/3G/oGGnEUGuoNnd6qoZuqltyKEsyzVJq5I6rnUp6SjGeGhESikzzlc1eL7opfuVbrqbU1Zw9NCgtQMaZpY0eNnaaL2fHusvTK5vKu7sjSS1Y4y3QUA6K3e3Mau5UFDyMP7tYF9o8cAHZv68vipoIJg971PZIZ5HiwdvYGGvFVFHmGmZ2MxwmQYPXubPl9Up0tfoMQGetXd6mRbvhBw+boZ6WF7Mbv1+GsHRk0fQmPAH1GfmZirbCfDJ61tw3Px8/8pZsPAG4jlVhcPgZ7adwNWBB68lkRQWFiTgFlbnLY3DGGM7izIJIyT/jjIvEJw6fdJTc6krDzh6aMwMP9bvDH4ADSsa9uSWVJkAAAAASUVORK5CYII=); 39 | } 40 | 41 | .table-responsive { 42 | overflow: auto; 43 | overflow-y: hidden; 44 | } 45 | 46 | no-wrap { 47 | width: 1px; 48 | white-space: nowrap; 49 | } 50 | -------------------------------------------------------------------------------- /src/DotNetStatus/assets/js/AppInsights.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | var appInsights = window.appInsights || function (config) { 5 | function s(config) { t[config] = function () { var i = arguments; t.queue.push(function () { t[config].apply(t, i) }) } } var t = { config: config }, r = document, f = window, e = "script", o = r.createElement(e), i, u; for (o.src = config.url || "//az416426.vo.msecnd.net/scripts/a/ai.0.js", r.getElementsByTagName(e)[0].parentNode.appendChild(o), t.cookie = r.cookie, t.queue = [], i = ["Event", "Exception", "Metric", "PageView", "Trace"]; i.length;) s("track" + i.pop()); return config.disableExceptionTracking || (i = "onerror", s("_" + i), u = f[i], f[i] = function (config, r, f, e, o) { var s = u && u(config, r, f, e, o); return s !== !0 && t["_" + i](config, r, f, e, o), s }), t 6 | }({ 7 | instrumentationKey: "1d7e09ed-05de-4699-97a4-2edbfdb0e139" 8 | }); 9 | 10 | window.appInsights = appInsights; 11 | appInsights.trackPageView(); 12 | -------------------------------------------------------------------------------- /src/DotNetStatus/assets/js/DotNetStatus.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | "use strict"; 5 | var sortArrowSpan = "Sort-Arrow-Span"; 6 | 7 | /// Remove the sort-Arrow-Span from all elements in the header section of an HTML table 8 | /// The header section object of an HTML table 9 | function removeSortArrowSpan(thead) { 10 | thead.find("#" + sortArrowSpan).remove(); 11 | } 12 | 13 | /// Sets the Sort-Arrow-Span on the Table Header table cell 14 | /// The table cell object from the header section of an HTML table 15 | /// Order by ascending or descending 16 | function setSortArrowSpan(headCell, order) { 17 | if (order === 1) { 18 | $(headCell).append(""); 19 | } else { 20 | $(headCell).append(""); 21 | } 22 | } 23 | 24 | /// Sets the data-SortDirection attribute on a table cell object from the header section of an HTML table 25 | /// HTMLTableHeader cell object 26 | /// Order by ascending or descending 27 | function setDataSortAttribute(headCell, order) { 28 | if (order === 1) { 29 | headCell.setAttribute("data-SortDirection", "ascending"); 30 | } else { 31 | headCell.setAttribute("data-SortDirection", "descending"); 32 | } 33 | } 34 | 35 | /// Fills an array with the rows from the body section of an HTML table 36 | /// The rows from the body section of an HTML table 37 | function fillArrayWithCellsFromRows(rows) { 38 | var cells, i, j; 39 | var arr = []; 40 | 41 | for (i = 0; i < rows.length; i += 1) { 42 | cells = rows[i].cells; 43 | arr[i] = []; 44 | for (j = 0; j < cells.length; j += 1) { 45 | arr[i][j] = cells[j].innerHTML; 46 | } 47 | } 48 | 49 | return arr; 50 | } 51 | 52 | /// Returns an array sorted by the specified column number and ordered by the orderending/descending parameter 53 | /// An array of items to sort 54 | /// Order by ascending or descending 55 | /// The column number to sort on 56 | /// Boolean representing whether column is a number or not 57 | function sortArray(arr, order, colToSortOn, isColumnANumber) { 58 | return arr.sort(function (a, b) { 59 | var x = a[colToSortOn]; 60 | var y = b[colToSortOn]; 61 | 62 | //if x and y are ints then compare by the value rather then by text 63 | if (isColumnANumber) { 64 | x = parseInt(x); 65 | y = parseInt(y); 66 | } 67 | 68 | if (x === y) { 69 | return 0; 70 | } else { 71 | if (x > y) { 72 | return order; 73 | } else { 74 | return -1 * order; 75 | } 76 | } 77 | }); 78 | } 79 | 80 | /// Sorts an rows of an HTML table body 81 | /// The HTMLelement object representing the header section of an HTML table 82 | /// The HTMLelement object representing the body section of an HTML table 83 | /// Integer of the column to sort on 84 | /// Boolean representing whether column is a number or not 85 | function tableSort(thead, tbody, colToSortOn, isColumnANumber) { 86 | var order, arr, i; 87 | var rows = tbody[0].rows; 88 | 89 | //Compute whether to sort ascending or descending based on the the data-SortDirection attribute 90 | var headCell = thead[0].rows[0].cells[colToSortOn]; 91 | if (headCell.hasAttribute("data-SortDirection") && headCell.getAttribute("data-SortDirection") === "descending") { 92 | order = 1; 93 | } else { 94 | order = -1; 95 | } 96 | 97 | //set sorting arrow and sortdirection attribute 98 | removeSortArrowSpan(thead); 99 | setDataSortAttribute(headCell, order); 100 | setSortArrowSpan(headCell, order); 101 | 102 | //fill and sort the array of table rows 103 | arr = sortArray(fillArrayWithCellsFromRows(rows), order, colToSortOn, isColumnANumber); 104 | 105 | // replace existing rows with new rows created from the sorted array 106 | for (i = 0; i < rows.length; i += 1) { 107 | rows[i].innerHTML = "" + arr[i].join("") + ""; 108 | } 109 | } 110 | 111 | /// Returns a ChartJS pie chart config 112 | /// The values representing the data 113 | /// The labels of the values 114 | /// The colors to be used for each data value 115 | function GetPieChartConfig(data, labels, colors) { 116 | var config = { 117 | type: 'pie', 118 | data: { 119 | datasets: [{ 120 | data: data, 121 | backgroundColor: colors 122 | }], 123 | labels: labels 124 | }, 125 | options: { 126 | responsive: true, 127 | showTooltips: true 128 | } 129 | }; 130 | 131 | return config; 132 | } 133 | 134 | /// Returns a ChartJS stacked bar chart config 135 | /// The chart datasets data values 136 | /// The labels of the datasets 137 | function GetStackedBarChartConfig(dataSets, labels) { 138 | var barChartData = { 139 | labels: labels, 140 | datasets: dataSets 141 | }; 142 | 143 | var chartconfig = { 144 | type: 'bar', 145 | data: barChartData, 146 | options: { 147 | responsive: true, 148 | scales: { 149 | xAxes: [{ 150 | stacked: true 151 | }], 152 | yAxes: [{ 153 | stacked: true 154 | }] 155 | } 156 | } 157 | }; 158 | 159 | return chartconfig; 160 | } 161 | 162 | /// Refreshes the contentPlaceHolder HTMLElement with new data from the data service 163 | /// The HTMLelement object to replace the content of 164 | /// The route to call on the data service 165 | function refreshChart(contentPlaceHolder, route) { 166 | 167 | contentPlaceHolder.hide(); 168 | $.get('/Data/' + route, function (data) { 169 | contentPlaceHolder.html(data); 170 | contentPlaceHolder.fadeIn(1000); 171 | }); 172 | } 173 | 174 | -------------------------------------------------------------------------------- /src/DotNetStatus/assets/js/PopoverHelpers.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | function InitializePopovers() { 5 | $(".popup-marker").popover(); 6 | $(".popup-marker").on('click', function (e) { e.preventDefault(); return true; }); 7 | 8 | $('.popup-marker').popover(); 9 | 10 | $('body').on('click', function (e) { 11 | $('.popup-marker').each(function () { 12 | if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover-marker').has(e.target).length === 0) { 13 | $(this).popover('hide'); 14 | } 15 | }); 16 | }); 17 | } 18 | 19 | $(document).ready(InitializePopovers); 20 | -------------------------------------------------------------------------------- /src/DotNetStatus/assets/js/Search.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. 3 | 4 | $(document).ready(function () { 5 | var $searchTextBox = $("#searchTextBox"); 6 | var $searchButton = $("#searchButton"); 7 | var $hiddenDocId = $("#docId"); 8 | 9 | function DisableButton() { 10 | $searchButton.attr('disabled', 'disabled'); 11 | } 12 | 13 | function EnableButton() { 14 | $searchButton.removeAttr('disabled'); 15 | } 16 | 17 | function InvalidTextBox() { 18 | $searchTextBox.addClass('invalid-query'); 19 | } 20 | 21 | function ValidTextBox() { 22 | $searchTextBox.removeClass('invalid-query'); 23 | } 24 | 25 | DisableButton(); 26 | 27 | function ValidateTextBox(url) { 28 | var query = $searchTextBox.val(); 29 | 30 | // If search box is empty, invalid mark (if applied) 31 | if (query == '') { 32 | ValidTextBox(); 33 | } else { 34 | // Call API to see if search box contains valid query 35 | $.ajax({ 36 | type: "GET", 37 | url: url, 38 | data: "query=" + query, 39 | error: function (err) { 40 | InvalidTextBox(); 41 | DisableButton(); 42 | }, 43 | success: function (output) { 44 | ValidTextBox(); 45 | EnableButton(); 46 | $hiddenDocId.val(output.docId); 47 | } 48 | }); 49 | } 50 | } 51 | 52 | var autocompleteUrl = $searchTextBox.data("autocomplete-url"); 53 | var validateUrl = $searchTextBox.data("autocomplete-validate-url"); 54 | 55 | $searchTextBox.change(function () { 56 | ValidateTextBox(validateUrl) 57 | }); 58 | 59 | $searchTextBox.keyup(function (e) { 60 | // Check if ESC was pressed 61 | if (e.keyCode == 27) { 62 | $searchTextBox.val(""); 63 | } 64 | 65 | ValidateTextBox(validateUrl); 66 | }); 67 | 68 | // Initialize Bootstrap autocomplete 69 | $searchTextBox.autocomplete({ 70 | source: autocompleteUrl, 71 | focus: function (event, ui) { 72 | $searchTextBox.val(ui.item.fullName); 73 | $hiddenDocId.val(ui.item.docId); 74 | 75 | ValidateTextBox(validateUrl); 76 | 77 | return false; 78 | }, 79 | select: function (event, ui) { 80 | $hiddenDocId.val(ui.item.docId); 81 | $searchTextBox.val(ui.item.fullName); 82 | 83 | ValidateTextBox(validateUrl); 84 | 85 | $searchButton.click(); 86 | 87 | return true; 88 | } 89 | }) 90 | // Display only full name from results data 91 | .autocomplete("instance")._renderItem = function (ul, item) { 92 | return $("
  • ") 93 | .append("" + item.fullName + "") 94 | .appendTo(ul); 95 | }; 96 | }); 97 | -------------------------------------------------------------------------------- /src/DotNetStatus/assets/js/ie10-viewport-bug-workaround.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * IE10 viewport hack for Surface/desktop Windows 8 bug 3 | * Copyright 2014 Twitter, Inc. 4 | * Licensed under the Creative Commons Attribution 3.0 Unported License. For 5 | * details, see http://creativecommons.org/licenses/by/3.0/. 6 | */ 7 | 8 | // See the Getting Started docs for more information: 9 | // http://getbootstrap.com/getting-started/#support-ie10-width 10 | 11 | (function () { 12 | 'use strict'; 13 | if (navigator.userAgent.match(/IEMobile\/10\.0/)) { 14 | var msViewportStyle = document.createElement('style') 15 | msViewportStyle.appendChild( 16 | document.createTextNode( 17 | '@-ms-viewport{width:auto!important}' 18 | ) 19 | ) 20 | document.querySelector('head').appendChild(msViewportStyle) 21 | } 22 | })(); 23 | -------------------------------------------------------------------------------- /src/DotNetStatus/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DotNetStatus", 3 | "private": true, 4 | "dependencies": { 5 | "jquery": "2.1.3", 6 | "jquery-ui": "1.11.2", 7 | "jquery-ui-smoothness": "1.11.1", 8 | "bootstrap": "3.3.1", 9 | "chartjs": "2.0.0-beta" 10 | }, 11 | "exportsOverride": { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/DotNetStatus/gulpfile.js: -------------------------------------------------------------------------------- 1 | /// 2 | var gulp = require("gulp"), 3 | rimraf = require("rimraf"), 4 | concat = require("gulp-concat"), 5 | cssmin = require("gulp-cssmin"), 6 | uglify = require("gulp-uglify"), 7 | gulpPath = require('gulp-path'), 8 | gutil = require('gulp-util'); 9 | 10 | var assets = new gulpPath.Base({ 11 | src: './assets/', 12 | dest: './wwwroot/' 13 | }), 14 | root = new gulpPath.Base(); 15 | 16 | var paths = { 17 | lib: assets.Path('lib'), 18 | bower: root.Path('bower_components'), 19 | css: assets.Path('css', 'css'), 20 | js: assets.Path('js', 'js'), 21 | }; 22 | 23 | paths.minCss = paths.css.files('/**/*', 'min.css')[0]; 24 | paths.minJs = paths.js.files('/**/*', 'min.js')[0]; 25 | 26 | paths.concatJsDest = gulpPath.filesPaths(paths.js.dest, 'site', 'min.js')[0]; 27 | paths.concatCssDest = gulpPath.filesPaths(paths.css.dest, 'site', 'min.css')[0]; 28 | 29 | gulp.task("clean:js", function (callback) { 30 | var destination = paths.js.dest[0]; 31 | gutil.log('Cleaning [' + destination + '] ...'); 32 | rimraf(destination, callback); 33 | }); 34 | 35 | gulp.task("clean:css", function (callback) { 36 | var destination = paths.css.dest[0]; 37 | gutil.log('Cleaning [' + destination + '] ...'); 38 | rimraf(destination, callback); 39 | }); 40 | 41 | gulp.task("clean:lib", function (callback) { 42 | var destination = paths.lib.dest[0]; 43 | 44 | gutil.log('Cleaning [' + destination + '] ...'); 45 | rimraf(destination, callback); 46 | }); 47 | 48 | gulp.task("clean", ["clean:js", "clean:css", "clean:lib"]); 49 | 50 | gulp.task("min:js", function () { 51 | var source = paths.js.src[0]; 52 | var destination = paths.concatJsDest; 53 | var minifiedFiles = '!' + paths.minJs; 54 | 55 | gutil.log('Concat files from ' + source + ' except [' + minifiedFiles +'] to ' + destination + '...'); 56 | 57 | gulp.src([source, minifiedFiles], { base: "." }) 58 | .pipe(concat(destination)) 59 | .pipe(uglify()) 60 | .pipe(gulp.dest(".")); 61 | }); 62 | 63 | gulp.task("min:css", function () { 64 | var source = paths.css.src[0]; 65 | var destination = paths.concatCssDest; 66 | var minifiedFiles = '!' + paths.minCss; 67 | 68 | gutil.log('Concat files from ' + source + ' except [' + minifiedFiles +'] to ' + destination + '...'); 69 | 70 | gulp.src([source, "!" + minifiedFiles]) 71 | .pipe(concat(destination)) 72 | .pipe(cssmin()) 73 | .pipe(gulp.dest(".")); 74 | }); 75 | 76 | gulp.task("copy", function () { 77 | var bower = { 78 | "bootstrap": "bootstrap/dist/**/*.{js,map,css,ttf,svg,woff,eot}", 79 | "jquery": "jquery/dist/jquery*.{js,map}", 80 | "jquery-ui": "jquery-ui/jquery-ui.js", 81 | "jquery-ui-smoothness": "jquery-ui-smoothness/jquery-ui.css", 82 | "chartjs" : "chartjs/Chart*" 83 | }; 84 | 85 | gutil.log('Copying bower_components to wwwroot/lib...'); 86 | 87 | for (var module in bower) { 88 | 89 | var bowerSource = paths.bower.files(bower[module])[0] 90 | var libFolder = gulpPath.filesPaths(paths.lib.dest, module)[0]; 91 | 92 | gutil.log('Source [' + bowerSource + '], Destination [' + libFolder + ']'); 93 | 94 | gulp.src(bowerSource) 95 | .pipe(gulp.dest(libFolder)); 96 | }; 97 | }); 98 | 99 | gulp.task("min", ["min:js", "min:css"]); 100 | 101 | gulp.task("build", ["copy", "min"]); 102 | -------------------------------------------------------------------------------- /src/DotNetStatus/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.0", 3 | "name": "dotnetstatus", 4 | "description": "Dependencies for DotNetStatus website", 5 | "license": "MIT", 6 | "repository": "https://github.com/microsoft/dotnet-apiweb", 7 | "devDependencies": { 8 | "gulp": "3.9.1", 9 | "gulp-concat": "2.6.0", 10 | "gulp-cssmin": "0.1.7", 11 | "gulp-uglify": "2.0.0", 12 | "gulp-path": "3.0.3", 13 | "gulp-util": "3.0.7", 14 | "rimraf": "2.5.4" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/DotNetStatus/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.AspNetCore.Diagnostics": "1.0.0", 4 | "Microsoft.AspNetCore.Mvc": "1.0.1", 5 | "Microsoft.AspNetCore.Mvc.Core": "1.0.1", 6 | "Microsoft.AspNetCore.Razor.Tools": { 7 | "version": "1.0.0-preview2-final", 8 | "type": "build" 9 | }, 10 | "Microsoft.AspNetCore.Routing": "1.0.1", 11 | "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", 12 | "Microsoft.AspNetCore.Server.Kestrel": "1.0.1", 13 | "Microsoft.AspNetCore.StaticFiles": "1.0.0", 14 | "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0", 15 | "Microsoft.Extensions.Configuration.Json": "1.0.0", 16 | "Microsoft.Extensions.Logging": "1.0.0", 17 | "Microsoft.Extensions.Logging.Console": "1.0.0", 18 | "Microsoft.Extensions.Logging.Debug": "1.0.0", 19 | "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0", 20 | "Microsoft.Fx.Portability": "2.1.0-alpha-00126", 21 | "Microsoft.NETCore.App": { 22 | "version": "1.0.1", 23 | "type": "platform" 24 | }, 25 | "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0", 26 | "System.Diagnostics.TraceSource": "4.0.0", 27 | "System.Net.Http": "4.1.0" 28 | }, 29 | 30 | "tools": { 31 | "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview2-final", 32 | "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview2-final" 33 | }, 34 | 35 | "commands": { 36 | "web": "Microsoft.AspNet.Server.Kestrel" 37 | }, 38 | 39 | "frameworks": { 40 | "netcoreapp1.0": { 41 | "imports": [ 42 | "dotnet5.6", 43 | "portable-net45+win8" 44 | ] 45 | } 46 | }, 47 | "buildOptions": { 48 | "emitEntryPoint": true, 49 | "preserveCompilationContext": true 50 | }, 51 | 52 | "runtimeOptions": { 53 | "configProperties": { 54 | "System.GC.Server": true 55 | } 56 | }, 57 | 58 | "publishOptions": { 59 | "include": [ 60 | "wwwroot", 61 | "**/*.cshtml", 62 | "appsettings.json", 63 | "web.config" 64 | ], 65 | "exclude": [ 66 | "node_modules", 67 | "bower_components", 68 | "**.xproj", 69 | "**.user", 70 | "**.vspscc" 71 | ] 72 | }, 73 | "scripts": { 74 | "prepublish": [ "npm install", "bower install", "gulp clean", "gulp build" ], 75 | "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ] 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/DotNetStatus/web.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/DotNetStatus/wwwroot/img/dotnet.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-apiweb/80ae5f043406ee1fa85baf5ddfe7f7f7e6b1c83f/src/DotNetStatus/wwwroot/img/dotnet.ico -------------------------------------------------------------------------------- /src/DotNetStatus/wwwroot/img/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/dotnet-apiweb/80ae5f043406ee1fa85baf5ddfe7f7f7e6b1c83f/src/DotNetStatus/wwwroot/img/loader.gif --------------------------------------------------------------------------------