mirror of
https://github.com/unclshura/BlazorOpenApi.git
synced 2025-12-21 09:51:53 +00:00
Add project files.
This commit is contained in:
commit
1744a7829d
63
.gitattributes
vendored
Normal file
63
.gitattributes
vendored
Normal file
@ -0,0 +1,63 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
* text=auto
|
||||
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
365
.gitignore
vendored
Normal file
365
.gitignore
vendored
Normal file
@ -0,0 +1,365 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Oo]ut/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
*.patch
|
||||
31
BlazorOpenApi.sln
Normal file
31
BlazorOpenApi.sln
Normal file
@ -0,0 +1,31 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.8.34511.84
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorOpenApi.Demo", "Demo\BlazorOpenApi.Demo.csproj", "{23C0112B-477D-40F2-8088-0C086D5E7A7A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorOpenApi", "BlazorOpenApi\BlazorOpenApi.csproj", "{57AD9505-4132-4D79-BF67-03E9F5FC0483}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{23C0112B-477D-40F2-8088-0C086D5E7A7A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{23C0112B-477D-40F2-8088-0C086D5E7A7A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{23C0112B-477D-40F2-8088-0C086D5E7A7A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{23C0112B-477D-40F2-8088-0C086D5E7A7A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{57AD9505-4132-4D79-BF67-03E9F5FC0483}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{57AD9505-4132-4D79-BF67-03E9F5FC0483}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{57AD9505-4132-4D79-BF67-03E9F5FC0483}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{57AD9505-4132-4D79-BF67-03E9F5FC0483}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3E7BCFDA-CFF3-4DA3-9E81-1BA3F79B0247}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
19
BlazorOpenApi/ApiUtils.cs
Normal file
19
BlazorOpenApi/ApiUtils.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Markdig;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace BlazorOpenApi;
|
||||
|
||||
internal static class ApiUtils
|
||||
{
|
||||
public static MarkupString MarkdownToHtml(string? md)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(md))
|
||||
return new();
|
||||
|
||||
var pipeline = new MarkdownPipelineBuilder().UseAdvancedExtensions().Build();
|
||||
var html = Markdown.ToHtml(md, pipeline).ToString() ?? "";
|
||||
|
||||
return new (html);
|
||||
}
|
||||
|
||||
}
|
||||
10
BlazorOpenApi/BlazorOpenApi.csproj
Normal file
10
BlazorOpenApi/BlazorOpenApi.csproj
Normal file
@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Markdig" />
|
||||
<PackageReference Include="Microsoft.OpenApi.Readers" />
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
46
BlazorOpenApi/Controls/AnyControl.razor
Normal file
46
BlazorOpenApi/Controls/AnyControl.razor
Normal file
@ -0,0 +1,46 @@
|
||||
@using Microsoft.OpenApi.Any
|
||||
|
||||
@if (Value != null)
|
||||
{
|
||||
<div class="e-item">
|
||||
@switch (Value.AnyType)
|
||||
{
|
||||
case AnyType.Null:
|
||||
break;
|
||||
case AnyType.Primitive:
|
||||
{
|
||||
<span>@AsPrimitive?.PrimitiveType</span>
|
||||
}
|
||||
break;
|
||||
case AnyType.Array:
|
||||
{
|
||||
<span>[</span>
|
||||
@foreach (var element in AsArray!)
|
||||
{
|
||||
<AnyControl Value="@element" />
|
||||
}
|
||||
<span>]</span>
|
||||
}
|
||||
break;
|
||||
case AnyType.Object:
|
||||
{
|
||||
@foreach (var element in AsObject!)
|
||||
{
|
||||
<div class="e-name">@element.Key</div>
|
||||
<AnyControl Value="@element.Value" />
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public IOpenApiAny? Value { get; set; }
|
||||
|
||||
private IOpenApiPrimitive? AsPrimitive => Value as IOpenApiPrimitive;
|
||||
private OpenApiArray? AsArray => Value as OpenApiArray;
|
||||
private OpenApiObject? AsObject => Value as OpenApiObject;
|
||||
|
||||
}
|
||||
42
BlazorOpenApi/Controls/ComponentsControl.razor
Normal file
42
BlazorOpenApi/Controls/ComponentsControl.razor
Normal file
@ -0,0 +1,42 @@
|
||||
@using Microsoft.OpenApi.Models
|
||||
@if ( Value != null )
|
||||
{
|
||||
@if (Value.Schemas?.Count > 0)
|
||||
{
|
||||
<h3>Schemas</h3>
|
||||
@foreach (var (name, val) in Value.Schemas)
|
||||
{
|
||||
<h4>@name</h4>
|
||||
<SchemaControl Value="@val"/>
|
||||
}
|
||||
}
|
||||
|
||||
<ResponsesControl Value="@Value.Responses"/>
|
||||
|
||||
@if (Value.Parameters?.Count > 0)
|
||||
{
|
||||
<h3>Parameters</h3>
|
||||
@foreach (var (name, val) in Value.Parameters)
|
||||
{
|
||||
<h4>@name</h4>
|
||||
<ParametersControl Value="@ToList(val)" />
|
||||
}
|
||||
}
|
||||
|
||||
@if (Value.Examples?.Count > 0)
|
||||
{
|
||||
<h3>Examples</h3>
|
||||
@foreach (var (name, val) in Value.Examples)
|
||||
{
|
||||
<ExampleControl Example="@val" Name="@name"/>
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public OpenApiComponents? Value { get; set; }
|
||||
|
||||
private IList<OpenApiParameter> ToList(OpenApiParameter val)
|
||||
=> new List<OpenApiParameter>() { val };
|
||||
}
|
||||
30
BlazorOpenApi/Controls/DiscriminatorControl.razor
Normal file
30
BlazorOpenApi/Controls/DiscriminatorControl.razor
Normal file
@ -0,0 +1,30 @@
|
||||
@using Microsoft.OpenApi.Models
|
||||
|
||||
@if (Value != null)
|
||||
{
|
||||
<div class="descriminator">
|
||||
<Text Value="@Value.PropertyName" />
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>From</th>
|
||||
<th>To</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Value.Mapping)
|
||||
{
|
||||
<tr>
|
||||
<td>@item.Key</td>
|
||||
<td>@item.Value</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public OpenApiDiscriminator? Value { get; set; }
|
||||
}
|
||||
46
BlazorOpenApi/Controls/ExampleControl.razor
Normal file
46
BlazorOpenApi/Controls/ExampleControl.razor
Normal file
@ -0,0 +1,46 @@
|
||||
@using Microsoft.OpenApi.Any
|
||||
@using Microsoft.OpenApi.Models
|
||||
|
||||
@if (Value != null || Example != null )
|
||||
{
|
||||
<div class="e-title">
|
||||
@if (!string.IsNullOrWhiteSpace(Name))
|
||||
{
|
||||
<span class="e-name">@Name</span>
|
||||
@if (!string.IsNullOrWhiteSpace(Example?.Summary))
|
||||
{
|
||||
<span class="spacer">-</span>
|
||||
}
|
||||
}
|
||||
@if ( !string.IsNullOrWhiteSpace(Example?.Summary) )
|
||||
{
|
||||
<span>@Example.Summary </span>
|
||||
}
|
||||
</div>
|
||||
|
||||
if (Example != null)
|
||||
{
|
||||
<MarkdownControl Value="@Example.Description"/>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public IOpenApiAny? Value { get; set; }
|
||||
[Parameter]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public OpenApiExample? Example { get; set; }
|
||||
|
||||
public IOpenApiAny? Ex => Example != null ? Example.Value : Value;
|
||||
/*
|
||||
@if (Ex != null)
|
||||
{
|
||||
<div class="example">
|
||||
<AnyControl Value="@Ex"/>
|
||||
</div>
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
43
BlazorOpenApi/Controls/Expander.razor
Normal file
43
BlazorOpenApi/Controls/Expander.razor
Normal file
@ -0,0 +1,43 @@
|
||||
<div class="expander @Class">
|
||||
<div class="ex-header @HeaderClass">
|
||||
@Title
|
||||
<div onclick="@(() => Toggle())">
|
||||
@if (Collapsed)
|
||||
{
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 9L12 15L6 9" stroke="var(--oa-fg-lighter)" stroke-width="2" />
|
||||
</svg>
|
||||
}
|
||||
else
|
||||
{
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 15L12 9L6 15" stroke="var(--oa-fg-lighter)" stroke-width="2" />
|
||||
</svg>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if (!Collapsed && ChildContent != null)
|
||||
{
|
||||
@ChildContent
|
||||
}
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public RenderFragment? ChildContent { get; set; }
|
||||
[Parameter]
|
||||
public bool Collapsed { get; set; } = true;
|
||||
[Parameter]
|
||||
public string Title { get; set; } = "";
|
||||
[Parameter]
|
||||
public string HeaderClass { get; set; } = "";
|
||||
[Parameter]
|
||||
public string Class { get; set; } = "";
|
||||
|
||||
void Toggle()
|
||||
{
|
||||
Collapsed = !Collapsed;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
49
BlazorOpenApi/Controls/HeaderControl.razor
Normal file
49
BlazorOpenApi/Controls/HeaderControl.razor
Normal file
@ -0,0 +1,49 @@
|
||||
@using System.Text.Json
|
||||
@using Microsoft.OpenApi.Models
|
||||
@using Microsoft.OpenApi.Readers
|
||||
|
||||
@if (Value != null)
|
||||
{
|
||||
<div class="header">
|
||||
<h1 class="h-title">@Value.Title <span class="h-version">@Value.Version</span></h1>
|
||||
<div class="h-contact">
|
||||
@if (!string.IsNullOrWhiteSpace(Value.Contact?.Name))
|
||||
{
|
||||
<div class="h-name">
|
||||
@Value.Contact.Name
|
||||
</div>
|
||||
}
|
||||
@if (Value.Contact?.Url != null)
|
||||
{
|
||||
<div class="h-url">
|
||||
@Value.Contact.Url
|
||||
</div>
|
||||
}
|
||||
@if (Value.Contact?.Email != null)
|
||||
{
|
||||
<div class="h-email">
|
||||
@Value.Contact.Email
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
@if (!string.IsNullOrWhiteSpace(DownloadUrl))
|
||||
{
|
||||
<a class="h-source-url" href="@DownloadUrl">@DownloadUrl</a>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(Value.Description))
|
||||
{
|
||||
<h2>Description</h2>
|
||||
<MarkdownControl Value="@Value.Description"/>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public OpenApiInfo? Value { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string DownloadUrl { get; set; } = "";
|
||||
|
||||
}
|
||||
64
BlazorOpenApi/Controls/IndicatorControl.razor
Normal file
64
BlazorOpenApi/Controls/IndicatorControl.razor
Normal file
@ -0,0 +1,64 @@
|
||||
@if (Value)
|
||||
{
|
||||
<Tooltip Class="@RealClass" TooltipText="@TtText">
|
||||
@Name
|
||||
</Tooltip>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string Name { get; set; } = "";
|
||||
[Parameter]
|
||||
public string TooltipText { get; set; } = "";
|
||||
[Parameter]
|
||||
public bool Value { get; set; }
|
||||
[Parameter]
|
||||
public string Class { get; set; } = "";
|
||||
|
||||
private string RealClass => $"indicator {Class}";
|
||||
|
||||
private string? TtText => !string.IsNullOrWhiteSpace(TooltipText) ? "" : Name.ToLower() switch
|
||||
{
|
||||
"explode" => ExplodeTooltip,
|
||||
"deprecated" => DeprecatedTooltip,
|
||||
"required" => RequiredTooltip,
|
||||
"allowemptyvalue" => AllowEmptyValueTooltip,
|
||||
"allowreserved" => AllowReservedTooltip,
|
||||
_ => ""
|
||||
};
|
||||
|
||||
internal const string ExplodeTooltip =
|
||||
@"
|
||||
When this is true, parameter values of type array or object generate separate parameters
|
||||
for each value of the array or key-value pair of the map.
|
||||
For other types of parameters this property has no effect.
|
||||
When style is form, the default value is true.
|
||||
For all other styles, the default value is false.
|
||||
";
|
||||
internal const string DeprecatedTooltip =
|
||||
@"
|
||||
Specifies that a parameter is deprecated and SHOULD be transitioned out of usage.
|
||||
";
|
||||
internal const string RequiredTooltip =
|
||||
@"
|
||||
Determines whether this parameter is mandatory.
|
||||
If the parameter location is ""path"", this property is REQUIRED and its value MUST be true.
|
||||
Otherwise, the property MAY be included and its default value is false.
|
||||
";
|
||||
internal const string AllowEmptyValueTooltip =
|
||||
@"
|
||||
Sets the ability to pass empty-valued parameters.
|
||||
This is valid only for query parameters and allows sending a parameter with an empty value.
|
||||
Default value is false.
|
||||
If style is used, and if behavior is n/a (cannot be serialized),
|
||||
the value of allowEmptyValue SHALL be ignored.
|
||||
";
|
||||
internal const string AllowReservedTooltip =
|
||||
@"
|
||||
Determines whether the parameter value SHOULD allow reserved characters,
|
||||
as defined by RFC3986 :/?#[]@!$&'()*+,;= to be included without percent-encoding.
|
||||
This property only applies to parameters with an in value of query.
|
||||
The default value is false.
|
||||
";
|
||||
|
||||
}
|
||||
9
BlazorOpenApi/Controls/MarkdownControl.razor
Normal file
9
BlazorOpenApi/Controls/MarkdownControl.razor
Normal file
@ -0,0 +1,9 @@
|
||||
@if (!string.IsNullOrWhiteSpace(Value))
|
||||
{
|
||||
<div class="markdown">@ApiUtils.MarkdownToHtml(Value)</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string? Value { get; set; }
|
||||
}
|
||||
75
BlazorOpenApi/Controls/OperationControl.razor
Normal file
75
BlazorOpenApi/Controls/OperationControl.razor
Normal file
@ -0,0 +1,75 @@
|
||||
@using System.Text.Json
|
||||
@using Microsoft.OpenApi.Models
|
||||
@using Microsoft.OpenApi.Readers
|
||||
|
||||
@if (Value != null)
|
||||
{
|
||||
<div class="op-header @OperationClass" @onclick="Expand">
|
||||
<div class="op-type">@Operation</div>
|
||||
<div class="spacer op-header-text">-</div>
|
||||
<div class="op-header-text" id="@Value.OperationId">@Endpoint</div>
|
||||
<div class="spacer op-header-text">-</div>
|
||||
<div class="op-summary op-header-text">@Value.Summary</div>
|
||||
@if (Value.Tags.Count > 0)
|
||||
{
|
||||
<div class="op-tags">
|
||||
@foreach (var tag in Value.Tags)
|
||||
{
|
||||
<Tooltip class="op-tag" TooltipText="@tag.Description">
|
||||
<Text Class="op-tag-name" Value="@tag.Name" />
|
||||
</Tooltip>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
@if (_expanded)
|
||||
{
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 15L12 9L6 15" stroke="var(--oa-fg-lighter)" stroke-width="2" />
|
||||
</svg>
|
||||
}
|
||||
else
|
||||
{
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M18 9L12 15L6 9" stroke="var(--oa-fg-lighter)" stroke-width="2" />
|
||||
</svg>
|
||||
}
|
||||
|
||||
</div>
|
||||
@if ( _expanded )
|
||||
{
|
||||
<div class="operation">
|
||||
|
||||
@if (Value != null)
|
||||
{
|
||||
<MarkdownControl Value="@Value.Description" />
|
||||
|
||||
if (Value.Servers?.Count > 0)
|
||||
{
|
||||
<ServersControl Value="@Value.Servers" />
|
||||
}
|
||||
|
||||
<ParametersControl Value="@Value.Parameters"/>
|
||||
<ResponsesControl Value="@Value.Responses" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public OperationType Operation { get; set; }
|
||||
[Parameter]
|
||||
public OpenApiOperation? Value { get; set; }
|
||||
[Parameter]
|
||||
public string Endpoint { get; set; } = "";
|
||||
|
||||
private string OperationClass => $"op-{Operation.ToString().ToLower()}";
|
||||
|
||||
private bool _expanded = true;
|
||||
|
||||
private void Expand()
|
||||
{
|
||||
_expanded = !_expanded;
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
59
BlazorOpenApi/Controls/ParameterControl.razor
Normal file
59
BlazorOpenApi/Controls/ParameterControl.razor
Normal file
@ -0,0 +1,59 @@
|
||||
@using System.Text.Json
|
||||
@using Microsoft.OpenApi.Models
|
||||
@using Microsoft.OpenApi.Readers
|
||||
|
||||
@if (Value != null)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<SchemaControl Value="@Value.Schema" />
|
||||
</td>
|
||||
<td>
|
||||
<div class="p-attrs">
|
||||
<div class="p-name">@Value.Name</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="p-attrs">
|
||||
<div class="p-in @InClass(Value)">@Value.In</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="p-attrs">
|
||||
<ParameterStyleControl Value="@Value.Style" />
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="p-attrs">
|
||||
<div class="p-indicators">
|
||||
<IndicatorControl Name="Deprecated" Value="@Value.Deprecated" Class="i-deprecated" />
|
||||
<IndicatorControl Name="Required" Value="@Value.Required" Class="i-required"/>
|
||||
<IndicatorControl Name="AllowEmptyValue" Value="@Value.AllowEmptyValue" />
|
||||
<IndicatorControl Name="AllowReserved" Value="@Value.AllowReserved" />
|
||||
<IndicatorControl Name="Explode" Value="@Value.Explode" />
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="p-body">
|
||||
<MarkdownControl Value="@Value.Description" />
|
||||
<ExampleControl Value="@Value.Example" />
|
||||
@if (Value.Examples.Count > 0)
|
||||
{
|
||||
foreach (var (n, v) in Value.Examples)
|
||||
{
|
||||
<ExampleControl Example="@v" Name="@n" />
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public OpenApiParameter? Value { get; set; }
|
||||
|
||||
private string InClass(OpenApiParameter p) => Value == null ? "" : $"p-in-{p?.In?.ToString()?.ToLower()}";
|
||||
|
||||
}
|
||||
13
BlazorOpenApi/Controls/ParameterStyleControl.razor
Normal file
13
BlazorOpenApi/Controls/ParameterStyleControl.razor
Normal file
@ -0,0 +1,13 @@
|
||||
@using Microsoft.OpenApi.Models
|
||||
|
||||
@if ( Value != null )
|
||||
{
|
||||
<div class="p-style @StyleClass">@Value</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public ParameterStyle? Value { get; set; }
|
||||
|
||||
private string StyleClass => Value == null ? "" : $"p-style-{Value.ToString()?.ToLower()}";
|
||||
}
|
||||
34
BlazorOpenApi/Controls/ParametersControl.razor
Normal file
34
BlazorOpenApi/Controls/ParametersControl.razor
Normal file
@ -0,0 +1,34 @@
|
||||
@using System.Text.Json
|
||||
@using Microsoft.OpenApi.Models
|
||||
@using Microsoft.OpenApi.Readers
|
||||
|
||||
@if (Value?.Count > 0)
|
||||
{
|
||||
<table class="op-params parameter">
|
||||
@foreach (var p in Value)
|
||||
{
|
||||
<ParameterControl Value="@GetResolvedReference(p)"/>
|
||||
}
|
||||
</table>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public IList<OpenApiParameter>? Value { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
public OpenApiDocument? Api { get; set; }
|
||||
|
||||
private OpenApiParameter? GetResolvedReference(OpenApiParameter p)
|
||||
{
|
||||
if (p == null)
|
||||
return null;
|
||||
if (!p.UnresolvedReference || p.Reference == null || Api == null)
|
||||
return p;
|
||||
|
||||
if (!Api.Components.Parameters.TryGetValue(p.Reference.Id, out var resolved))
|
||||
return p;
|
||||
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
44
BlazorOpenApi/Controls/PathControl.razor
Normal file
44
BlazorOpenApi/Controls/PathControl.razor
Normal file
@ -0,0 +1,44 @@
|
||||
@using System.Text.Json
|
||||
@using Microsoft.OpenApi.Models
|
||||
@using Microsoft.OpenApi.Readers
|
||||
|
||||
@if (!string.IsNullOrWhiteSpace(Key) || Value != null)
|
||||
{
|
||||
@if (!string.IsNullOrWhiteSpace(@Value?.Summary) || !string.IsNullOrWhiteSpace(Value?.Description))
|
||||
{
|
||||
<div class="pa-header">
|
||||
<h3>@Key</h3>
|
||||
<div class="spacer">-</div>
|
||||
<div class="pa-summary">@Value?.Summary</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="path">
|
||||
@if (Value != null)
|
||||
{
|
||||
<MarkdownControl Value="@Value.Description" />
|
||||
|
||||
if (Value.Servers?.Count > 0)
|
||||
{
|
||||
<ServersControl Value="@Value.Servers" />
|
||||
}
|
||||
|
||||
@if (Value.Operations?.Count > 0)
|
||||
{
|
||||
<div class="operations">
|
||||
@foreach (var (key, op) in @Value.Operations.Where(x => x.Value != null))
|
||||
{
|
||||
<OperationControl Endpoint="@Key" Operation="@key" Value="@op" />
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string? Key { get; set; }
|
||||
[Parameter]
|
||||
public OpenApiPathItem? Value { get; set; }
|
||||
}
|
||||
121
BlazorOpenApi/Controls/ResponseControl.razor
Normal file
121
BlazorOpenApi/Controls/ResponseControl.razor
Normal file
@ -0,0 +1,121 @@
|
||||
@using Microsoft.OpenApi.Models
|
||||
|
||||
@if (ResolvedValue != null)
|
||||
{
|
||||
<div class="response">
|
||||
<MarkdownControl Value="@ResolvedValue.Description" />
|
||||
|
||||
@if (ResolvedValue.Headers.Count > 0)
|
||||
{
|
||||
<table>
|
||||
@foreach (var (key, val) in ResolvedValue.Headers)
|
||||
{
|
||||
<tr>
|
||||
<td class="p-name">@key</td>
|
||||
<td>
|
||||
<div class="parameter">
|
||||
<div class="p-attrs">
|
||||
<ParameterStyleControl Value="@val.Style" />
|
||||
<div class="p-indicators">
|
||||
<IndicatorControl Name="Deprecated" Value="@val.Deprecated" Class="i-deprecated" />
|
||||
<IndicatorControl Name="Required" Value="@val.Required" Class="i-required" />
|
||||
<IndicatorControl Name="AllowEmptyResolvedValue" Value="@val.AllowEmptyValue" />
|
||||
<IndicatorControl Name="AllowReserved" Value="@val.AllowReserved" />
|
||||
<IndicatorControl Name="Explode" Value="@val.Explode" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="p-body">
|
||||
<SchemaControl Value="@val.Schema" />
|
||||
|
||||
@if (val.Content.Count > 0)
|
||||
{
|
||||
<table>
|
||||
@foreach (var (k, v) in val.Content)
|
||||
{
|
||||
<tr>
|
||||
<td>@k</td>
|
||||
<td>
|
||||
<SchemaControl Value="@v.Schema" />
|
||||
@if (v.Encoding.Count > 0)
|
||||
{
|
||||
<table class="r-encoding">
|
||||
@foreach (var (ename, eval) in v.Encoding)
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
<div class="e-name">@ename</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="e-name">@eval.ContentType</div>
|
||||
</td>
|
||||
<td>
|
||||
<ParameterStyleControl Value="@eval.Style" />
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
}
|
||||
<ExampleControl Value="@v.Example" />
|
||||
@foreach (var (ename, eval) in val.Examples)
|
||||
{
|
||||
<ExampleControl Example="@eval" Name="@ename" />
|
||||
}
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
}
|
||||
|
||||
<ExampleControl Value="@val.Example" />
|
||||
@if (val.Examples.Count > 0)
|
||||
{
|
||||
foreach (var (n, v) in val.Examples)
|
||||
{
|
||||
<ExampleControl Example="@v" Name="@n" />
|
||||
}
|
||||
}
|
||||
<MarkdownControl Value="@val.Description" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
}
|
||||
@if ( ResolvedValue.Content.Count > 0 )
|
||||
{
|
||||
@foreach (var (key, val) in ResolvedValue.Content)
|
||||
{
|
||||
<div class="p-name">@key</div>
|
||||
<div class="p-body">
|
||||
<SchemaControl Value="@val.Schema"/>
|
||||
</div>
|
||||
|
||||
}
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public OpenApiResponse? Value { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
public OpenApiDocument? Api { get; set; }
|
||||
|
||||
private OpenApiResponse? ResolvedValue
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Value?.Reference == null || Api == null || Value?.UnresolvedReference != true)
|
||||
return Value;
|
||||
|
||||
if (!Api.Components.Responses.TryGetValue(Value.Reference.Id, out var resolved))
|
||||
return Value;
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
}
|
||||
35
BlazorOpenApi/Controls/ResponsesControl.razor
Normal file
35
BlazorOpenApi/Controls/ResponsesControl.razor
Normal file
@ -0,0 +1,35 @@
|
||||
@using Microsoft.OpenApi.Models
|
||||
|
||||
@if (Value?.Count > 0)
|
||||
{
|
||||
<div class="responses">
|
||||
<div class="r-title">Responces</div>
|
||||
<table>
|
||||
@foreach (var (name, val) in Value)
|
||||
{
|
||||
<tr>
|
||||
<td><div class="r-name @GetClass(name)">@name</div></td>
|
||||
<td>
|
||||
<ResponseControl Value="@val"/>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public IDictionary<string, OpenApiResponse>? Value { get; set; }
|
||||
|
||||
private static string GetClass(string name)
|
||||
{
|
||||
if (name.StartsWith("2"))
|
||||
return "r-success";
|
||||
if (name.StartsWith("4"))
|
||||
return "r-auth";
|
||||
if (name.StartsWith("5"))
|
||||
return "r-error";
|
||||
return "";
|
||||
}
|
||||
}
|
||||
108
BlazorOpenApi/Controls/SchemaChildControl.razor
Normal file
108
BlazorOpenApi/Controls/SchemaChildControl.razor
Normal file
@ -0,0 +1,108 @@
|
||||
@using Microsoft.OpenApi.Models
|
||||
|
||||
@if ( Value != null )
|
||||
{
|
||||
<tr>
|
||||
<td>
|
||||
@if (Value.Type == "array")
|
||||
{
|
||||
<Expander HeaderClass="s-type" Class="s-bg-odd" Title="@ArrayText">
|
||||
<div class="s-nested">
|
||||
<SchemaControl Value="@Value.Items" />
|
||||
</div>
|
||||
</Expander>
|
||||
}
|
||||
else if (Value.Type == "object")
|
||||
{
|
||||
<Expander HeaderClass="s-type" Class="s-bg-odd" Title="@ObjectText">
|
||||
<div class="s-props s-nested">
|
||||
<table class="schema">
|
||||
@foreach (var p in Value.Properties)
|
||||
{
|
||||
<SchemaChildControl Value="@p.Value" Title="@p.Key" Required="@IsRequired(p.Key)" />
|
||||
}
|
||||
</table>
|
||||
</div>
|
||||
</Expander>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div>
|
||||
<Text Value="@TypeText" Class="s-type" />
|
||||
</div>
|
||||
}
|
||||
</td>
|
||||
<td>
|
||||
<Text Class="s-title" Value="@TitleText" />
|
||||
</td>
|
||||
<td>
|
||||
<IndicatorControl Name="Required" Value="@Required" Class="i-required" />
|
||||
<IndicatorControl Name="Deprecated" Value="@Value.Deprecated" Class="i-deprecated" />
|
||||
</td>
|
||||
<td>
|
||||
<MarkdownControl Value="@Value.Description" />
|
||||
</td>
|
||||
<td>
|
||||
@if (Value.AdditionalPropertiesAllowed && Value.AdditionalProperties != null)
|
||||
{
|
||||
<div class="s-additional-props">
|
||||
<SchemaControl Value="@Value.AdditionalProperties" />
|
||||
</div>
|
||||
}
|
||||
|
||||
<DiscriminatorControl Value="@Value.Discriminator" />
|
||||
<ExampleControl Value="@Value.Example" />
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public OpenApiSchema? Value { get; set; }
|
||||
[Parameter]
|
||||
public string? Title { get; set; }
|
||||
[Parameter]
|
||||
public bool Required { get; set; }
|
||||
|
||||
private string TitleText => (string.IsNullOrWhiteSpace(Title) ? Value?.Title : Title) ?? "";
|
||||
|
||||
private string ArrayText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Value?.Type != "array")
|
||||
return "";
|
||||
|
||||
var nullable = Value.Nullable ? "?" : "";
|
||||
var itemsType = $"{Value.Items?.Type ?? "-string-"}{nullable}";
|
||||
|
||||
if (Value.MinItems != null || Value.MaxItems != null)
|
||||
return $"{itemsType} [{(Value.MinItems == null ? "" : Value.MinItems.Value)}..{(Value.MaxItems == null ? "" : Value.MaxItems.Value)}]";
|
||||
return $"{itemsType} []";
|
||||
}
|
||||
}
|
||||
|
||||
private string ObjectText
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Value?.Type != "object")
|
||||
return "";
|
||||
var nullable = Value.Nullable ? "?" : "";
|
||||
if (Value.MinProperties != null || Value.MaxProperties != null)
|
||||
return $"object{nullable} {{{(Value.MinProperties == null ? "" : Value.MinProperties.Value)}..{(Value.MaxProperties == null ? "" : Value.MaxProperties.Value)}}}";
|
||||
return $"object{nullable}";
|
||||
}
|
||||
}
|
||||
|
||||
private string TypeText
|
||||
{
|
||||
get
|
||||
{
|
||||
var nullable = (Value?.Nullable ?? false) ? "?" : "";
|
||||
return $"{Value?.Format ?? "string"}{nullable}";
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsRequired(string name) => Value?.Required.Contains(name) ?? false;
|
||||
}
|
||||
33
BlazorOpenApi/Controls/SchemaControl.razor
Normal file
33
BlazorOpenApi/Controls/SchemaControl.razor
Normal file
@ -0,0 +1,33 @@
|
||||
@using Microsoft.OpenApi.Models
|
||||
|
||||
@if ( ResolvedValue != null )
|
||||
{
|
||||
<table class="schema">
|
||||
<SchemaChildControl Value="@ResolvedValue" Title="@Title" Required="@Required" />
|
||||
</table>
|
||||
}
|
||||
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public OpenApiSchema? Value { get; set; }
|
||||
[Parameter]
|
||||
public string? Title { get; set; }
|
||||
[Parameter]
|
||||
public bool Required { get; set; }
|
||||
|
||||
[CascadingParameter]
|
||||
public OpenApiDocument? Api { get; set; }
|
||||
|
||||
private OpenApiSchema? ResolvedValue
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Api == null || Value?.Reference == null )
|
||||
return Value;
|
||||
if (!Api.Components.Schemas.TryGetValue(Value.Reference.Id, out var resolved))
|
||||
return Value;
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
}
|
||||
69
BlazorOpenApi/Controls/ServersControl.razor
Normal file
69
BlazorOpenApi/Controls/ServersControl.razor
Normal file
@ -0,0 +1,69 @@
|
||||
@using System.Text.Json
|
||||
@using Microsoft.OpenApi.Models
|
||||
@using Microsoft.OpenApi.Readers
|
||||
|
||||
@if (Value != null && Value.Count > 0)
|
||||
{
|
||||
<h2>Servers</h2>
|
||||
<table class="servers">
|
||||
@foreach (var server in Value)
|
||||
{
|
||||
<tr>
|
||||
<td><MarkdownControl Value="@server.Description" /></td>
|
||||
<td><a class="sr-url" href="@server.Url">@server.Url</a></td>
|
||||
</tr>
|
||||
@if (server.Variables?.Count > 0)
|
||||
{
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div class="sr-vars">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var (key, val) in server.Variables.OrderBy(x => x.Key))
|
||||
{
|
||||
<tr>
|
||||
<td class="sr-var-name">@key</td>
|
||||
<MarkdownControl Value="@val.Description" />
|
||||
<td class="sr-var-val">
|
||||
<Text Class="sr-default" Value="@val.Default" />
|
||||
@if (val.Enum?.Count > 0)
|
||||
{
|
||||
<ul class="sr-enum">
|
||||
@foreach (var v in val.Enum)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(v))
|
||||
{
|
||||
<li>< empty string ></li>
|
||||
}
|
||||
else
|
||||
{
|
||||
<li>@v</li>
|
||||
}
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
}
|
||||
</table>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public IList<OpenApiServer>? Value { get; set; }
|
||||
}
|
||||
11
BlazorOpenApi/Controls/Text.razor
Normal file
11
BlazorOpenApi/Controls/Text.razor
Normal file
@ -0,0 +1,11 @@
|
||||
@if (!string.IsNullOrWhiteSpace(Value))
|
||||
{
|
||||
<div class="@Class">@Value</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public string? Value { get; set; }
|
||||
[Parameter]
|
||||
public string? Class { get; set; }
|
||||
}
|
||||
24
BlazorOpenApi/Controls/Tooltip.razor
Normal file
24
BlazorOpenApi/Controls/Tooltip.razor
Normal file
@ -0,0 +1,24 @@
|
||||
@if (string.IsNullOrWhiteSpace(TooltipText))
|
||||
{
|
||||
<div class="@Class">
|
||||
@ChildContent
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="tooltip">
|
||||
<div class="@Class">
|
||||
@ChildContent
|
||||
</div>
|
||||
<div class="tooltiptext">@TooltipText</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
public RenderFragment? ChildContent { get; set; }
|
||||
[Parameter]
|
||||
public string? TooltipText { get; set; }
|
||||
[Parameter]
|
||||
public string Class { get; set; } = "";
|
||||
}
|
||||
101
BlazorOpenApi/OpenAPIUIControl.razor
Normal file
101
BlazorOpenApi/OpenAPIUIControl.razor
Normal file
@ -0,0 +1,101 @@
|
||||
@using System.Text.Json
|
||||
@using Microsoft.OpenApi.Models
|
||||
@using Microsoft.OpenApi.Readers
|
||||
|
||||
@if (Palette != null )
|
||||
{
|
||||
@PaletteStr
|
||||
}
|
||||
|
||||
<div class="openapi-ui">
|
||||
<CascadingValue Value="@_api">
|
||||
<HeaderControl Value="@_api.Info" DownloadUrl="@Url"/>
|
||||
<ServersControl Value="@_api.Servers" />
|
||||
@if (_api.Paths?.Count > 0)
|
||||
{
|
||||
<h2>Endpoints</h2>
|
||||
foreach (var path in _api.Paths)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(path.Key) || path.Value != null)
|
||||
{
|
||||
<PathControl Key="@path.Key" Value="@path.Value" />
|
||||
}
|
||||
}
|
||||
}
|
||||
@if (_api.Components != null)
|
||||
{
|
||||
<h2>Components</h2>
|
||||
<ComponentsControl Value="@_api.Components"/>
|
||||
}
|
||||
</CascadingValue>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter] public string Url { get; set; } = "";
|
||||
[Parameter] public string Json { get; set; } = "";
|
||||
[Parameter] public OpenApiUiPalette? Palette { get; set; }
|
||||
|
||||
private string _loadedFor = "";
|
||||
private OpenApiDocument _api = new();
|
||||
|
||||
private MarkupString PaletteStr => Palette?.AsMarkupString ?? new();
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
var loadedFromUrl = _loadedFor == Url && !string.IsNullOrWhiteSpace(Url);
|
||||
var loadedFromJson = _loadedFor == Json && !string.IsNullOrWhiteSpace(Json);
|
||||
if (loadedFromUrl || loadedFromJson)
|
||||
return;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(Json))
|
||||
LoadFromJson();
|
||||
else if (!string.IsNullOrWhiteSpace(Url))
|
||||
await LoadFromUrl();
|
||||
|
||||
}
|
||||
|
||||
private async Task LoadFromUrl()
|
||||
{
|
||||
try
|
||||
{
|
||||
using var client = new HttpClient();
|
||||
|
||||
var jsonStream = await client.GetStreamAsync(Url);
|
||||
var reader = new OpenApiStreamReader();
|
||||
var res = await reader.ReadAsync(jsonStream);
|
||||
|
||||
|
||||
if (res?.OpenApiDocument == null)
|
||||
throw new InvalidOperationException($"Can't parse {Url}");
|
||||
|
||||
_api = res.OpenApiDocument;
|
||||
_loadedFor = Url;
|
||||
Json = "";
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
_loadedFor = "";
|
||||
_api = new();
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadFromJson()
|
||||
{
|
||||
try
|
||||
{
|
||||
var reader = new OpenApiStringReader();
|
||||
var res = reader.Read(Json, out var _)
|
||||
?? throw new InvalidOperationException($"Can't parse Json/Yaml");
|
||||
|
||||
_api = res;
|
||||
|
||||
_loadedFor = Url;
|
||||
// Url = ""; <-- do not set URL to ""
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
_loadedFor = "";
|
||||
_api = new();
|
||||
}
|
||||
}
|
||||
}
|
||||
79
BlazorOpenApi/OpenApiUiPalette.cs
Normal file
79
BlazorOpenApi/OpenApiUiPalette.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace BlazorOpenApi;
|
||||
|
||||
public class OpenApiUiPalette : ICloneable
|
||||
{
|
||||
public string BackgroundLighter { get; set; } = "#0000001f";
|
||||
public string BackgroundDarker { get; set; } = "#00000055";
|
||||
public string BackgroundDarkest { get; set; } = "#000000AA";
|
||||
|
||||
public string ForegroundNormal { get; set; } = "#e4e4e4";
|
||||
public string ForegroundLighter { get; set; } = "#ffffff";
|
||||
public string ForegroundDarker { get; set; } = "#A0A0A0";
|
||||
public string ForegroundDarkest { get; set; } = "#808080";
|
||||
|
||||
public string[/*8*/] Background { get; set; } = [
|
||||
"#3655a3",
|
||||
"#7a7620",
|
||||
"#9f4b1e",
|
||||
"#7e1b29",
|
||||
"#52628b",
|
||||
"#851192",
|
||||
"#266b67",
|
||||
"#456f2b"
|
||||
];
|
||||
|
||||
public string[/*8*/] Foreground { get; set; } = [
|
||||
"#7d98de",
|
||||
"#ded971",
|
||||
"#eda279",
|
||||
"#e97d8d",
|
||||
"#b1c0e6",
|
||||
"#e571f2",
|
||||
"#98e6e1",
|
||||
"#54b319"
|
||||
];
|
||||
|
||||
public MarkupString AsMarkupString => new MarkupString(
|
||||
$@"
|
||||
<style>
|
||||
.openapi-ui {{
|
||||
--oa-bg-lighter: {BackgroundLighter};
|
||||
--oa-bg-darker: {BackgroundDarker };
|
||||
--oa-bg-darkest: {BackgroundDarkest};
|
||||
|
||||
--oa-fg-normal: {ForegroundNormal };
|
||||
--oa-fg-lighter: {ForegroundLighter};
|
||||
--oa-fg-darker: {ForegroundDarker };
|
||||
--oa-fg-darkest: {ForegroundDarkest};
|
||||
|
||||
{string.Join("\n ", Background.Select((x,i) => $"--oa-bg-{i+1}: {x};"))}
|
||||
|
||||
{string.Join("\n ", Foreground.Select((x, i) => $"--oa-fg-{i+1}: {x};"))}
|
||||
}}
|
||||
</style>
|
||||
");
|
||||
|
||||
public OpenApiUiPalette Clone()
|
||||
{
|
||||
var other = new OpenApiUiPalette
|
||||
{
|
||||
BackgroundLighter = BackgroundLighter,
|
||||
BackgroundDarker = BackgroundDarker,
|
||||
BackgroundDarkest = BackgroundDarkest,
|
||||
|
||||
ForegroundNormal = ForegroundNormal,
|
||||
ForegroundLighter = ForegroundLighter,
|
||||
ForegroundDarker = ForegroundDarker,
|
||||
ForegroundDarkest = ForegroundDarkest,
|
||||
|
||||
Background = (string[])Background.Clone(),
|
||||
Foreground = (string[])Foreground.Clone()
|
||||
};
|
||||
|
||||
return other;
|
||||
}
|
||||
|
||||
object ICloneable.Clone() => Clone();
|
||||
}
|
||||
26
BlazorOpenApi/Properties/launchSettings.json
Normal file
26
BlazorOpenApi/Properties/launchSettings.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:57161",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5026",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
BlazorOpenApi/README.md
Normal file
3
BlazorOpenApi/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Blazor OpenAPI UI
|
||||
|
||||
Blazor implementation of SwaggerUI-like interface.
|
||||
10
BlazorOpenApi/_Imports.razor
Normal file
10
BlazorOpenApi/_Imports.razor
Normal file
@ -0,0 +1,10 @@
|
||||
@using System.Net.Http
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using BlazorOpenApi
|
||||
@using BlazorOpenApi.Controls
|
||||
392
BlazorOpenApi/wwwroot/css/openapi-ui.css
Normal file
392
BlazorOpenApi/wwwroot/css/openapi-ui.css
Normal file
@ -0,0 +1,392 @@
|
||||
.descriminator {}
|
||||
|
||||
.example {}
|
||||
.e-item {}
|
||||
.e-name {}
|
||||
.e-title {}
|
||||
|
||||
.expander {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.ex-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.header {}
|
||||
.h-contact {}
|
||||
.h-email {}
|
||||
.h-name {}
|
||||
.h-source-url {}
|
||||
.h-title {}
|
||||
.h-url {}
|
||||
.h-version {
|
||||
font-size: var(--oa-font-large);
|
||||
width: fit-content;
|
||||
color: var(--oa-fg-lighter);
|
||||
border-radius: 5px;
|
||||
background-color: var(--oa-bg-tag);
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.h1 {}
|
||||
.h2 {}
|
||||
|
||||
.indicator {
|
||||
color: var(--oa-fg-lighter);
|
||||
background-color: var(--oa-bg-lighter);
|
||||
font-size: var(--oa-font-smaller);
|
||||
height: fit-content;
|
||||
width: fit-content;
|
||||
margin-right: 5px;
|
||||
border-radius: 5px;
|
||||
margin-top: 3px;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.i-required {
|
||||
background-color: var(--oa-bg-3);
|
||||
}
|
||||
.i-deprecated {
|
||||
background-color: var(--oa-bg-4);
|
||||
}
|
||||
|
||||
.markdown {}
|
||||
|
||||
.operation {}
|
||||
.operations {}
|
||||
.op-params {}
|
||||
.op-header {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
margin-top: 16px;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
color: var(--oa-fg-lighter);
|
||||
}
|
||||
.op-summary {
|
||||
width: 100%;
|
||||
}
|
||||
.op-tags {
|
||||
display: flex;
|
||||
}
|
||||
.op-tag {
|
||||
background-color: var(--oa-bg-tag);
|
||||
color: var(--oa-fg-tag);
|
||||
border: solid 1px;
|
||||
margin: 1px;
|
||||
display: block;
|
||||
width: fit-content;
|
||||
padding: 2px;
|
||||
}
|
||||
.op-tag-name {
|
||||
font-size: var(--oa-font-small);
|
||||
white-space: nowrap;
|
||||
text-transform: lowercase;
|
||||
}
|
||||
.op-type {
|
||||
border: solid 1px;
|
||||
margin: 1px;
|
||||
display: block;
|
||||
width: fit-content;
|
||||
padding: 2px;
|
||||
padding-top: 3px;
|
||||
font-size: var(--oa-font-small);
|
||||
text-transform: uppercase;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.op-get {
|
||||
background-color: var(--oa-bg-op-get);
|
||||
}
|
||||
.op-put {
|
||||
background-color: var(--oa-bg-op-put);
|
||||
}
|
||||
.op-post {
|
||||
background-color: var(--oa-bg-op-post);
|
||||
}
|
||||
.op-delete {
|
||||
background-color: var(--oa-bg-op-delete);
|
||||
}
|
||||
.op-options {
|
||||
background-color: var(--oa-bg-op-options);
|
||||
}
|
||||
.op-head {
|
||||
background-color: var(--oa-bg-op-head);
|
||||
}
|
||||
.op-patch {
|
||||
background-color: var(--oa-bg-op-patch);
|
||||
}
|
||||
.op-trace {
|
||||
background-color: var(--oa-bg-op-trace);
|
||||
}
|
||||
.parameter {
|
||||
margin-left: 24px;
|
||||
}
|
||||
.p-attrs {
|
||||
display: flex;
|
||||
}
|
||||
.p-body {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.p-in {
|
||||
color: var(--oa-fg-lighter);
|
||||
font-size: var(--oa-font-smaller);
|
||||
height: fit-content;
|
||||
width: fit-content;
|
||||
margin-right: 5px;
|
||||
border-radius: 5px;
|
||||
margin-top: 3px;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
.p-in-query {
|
||||
background-color: var(--oa-bg-query);
|
||||
}
|
||||
.p-in-header {
|
||||
background-color: var(--oa-bg-header);
|
||||
}
|
||||
.p-in-path {
|
||||
background-color: var(--oa-bg-path);
|
||||
}
|
||||
.p-in-cookie {
|
||||
background-color: var(--oa-bg-cookie);
|
||||
}
|
||||
.p-indicators {
|
||||
display: flex;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.p-name {
|
||||
color: var(--oa-fg-1);
|
||||
margin-right: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.p-style {
|
||||
color: var(--oa-fg-lighter);
|
||||
font-size: var(--oa-font-smaller);
|
||||
height: fit-content;
|
||||
width: fit-content;
|
||||
margin-right: 5px;
|
||||
border-radius: 5px;
|
||||
margin-top: 3px;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
.p-style-matrix {
|
||||
background-color: var(--oa-bg-matrix);
|
||||
}
|
||||
.p-style-label {
|
||||
background-color: var(--oa-bg-label);
|
||||
}
|
||||
.p-style-form {
|
||||
background-color: var(--oa-bg-form);
|
||||
}
|
||||
.p-style-simple {
|
||||
background-color: var(--oa-bg-simple);
|
||||
}
|
||||
.p-style-spacedelimited {
|
||||
background-color: var(--oa-bg-spacedelimited);
|
||||
}
|
||||
.p-style-pipedelimited {
|
||||
background-color: var(--oa-bg-pipedelimited);
|
||||
}
|
||||
.p-style-deepobject {
|
||||
background-color: var(--oa-bg-deepobject);
|
||||
}
|
||||
|
||||
.path {}
|
||||
.pa-header {
|
||||
display: flex;
|
||||
}
|
||||
.pa-summary {
|
||||
}
|
||||
|
||||
.responses {}
|
||||
.response {}
|
||||
.r-name {
|
||||
border: solid 1px;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
.r-success {
|
||||
color: var(--oa-fg-8);
|
||||
}
|
||||
.r-auth {
|
||||
color: var(--oa-fg-3);
|
||||
}
|
||||
.r-error {
|
||||
color: var(--oa-fg-4);
|
||||
}
|
||||
.r-encoding{}
|
||||
|
||||
.schema {}
|
||||
.s-additional-props {}
|
||||
.s-props {}
|
||||
.s-title {
|
||||
color: var(--oa-fg-1);
|
||||
margin-right: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.s-nested {
|
||||
margin-left: 20px;
|
||||
}
|
||||
.s-type {
|
||||
color: var(--oa-fg-8);
|
||||
}
|
||||
.s-bg-odd {
|
||||
background-color: var(--oa-bg-lighter);
|
||||
}
|
||||
|
||||
.s-bg-even {
|
||||
background-color: var(--oa-bg-lighter);
|
||||
}
|
||||
|
||||
.servers {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.sr-server {
|
||||
display: flex;
|
||||
flex-direction:row;
|
||||
}
|
||||
.sr-default {}
|
||||
.sr-enum {}
|
||||
.sr-url {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.sr-var-name {}
|
||||
.sr-var-val {}
|
||||
.sr-vars {}
|
||||
.spacer {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.op-header-text {
|
||||
padding-top: 3px;
|
||||
}
|
||||
|
||||
.openapi-ui h1 {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.openapi-ui h2 {
|
||||
margin-top: 18px;
|
||||
}
|
||||
.openapi-ui h3 {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.openapi-ui h4 {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.openapi-ui .tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
border-bottom: 1px dotted black;
|
||||
}
|
||||
|
||||
.openapi-ui .tooltip .tooltiptext {
|
||||
visibility: hidden;
|
||||
width: fit-content;
|
||||
width: 201px;
|
||||
font-size: var(--oa-font-smaller);
|
||||
background-color: var(--oa-bg-darkest);
|
||||
color: var(--oa-fg-darker);
|
||||
text-align: center;
|
||||
border-radius: 6px;
|
||||
padding: 5px 0;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
bottom: 125%;
|
||||
left: 50%;
|
||||
margin-left: -60px;
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
|
||||
.openapi-ui .tooltip .tooltiptext::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-width: 5px;
|
||||
border-style: solid;
|
||||
border-color: #555 transparent transparent transparent;
|
||||
}
|
||||
|
||||
.openapi-ui .tooltip:hover .tooltiptext {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.openapi-ui span {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.openapi-ui td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.openapi-ui {
|
||||
--oa-bg-lighter: #0000001f;
|
||||
--oa-bg-darker: #00000055;
|
||||
--oa-bg-darkest: #000000AA;
|
||||
|
||||
--oa-fg-normal: #e4e4e4;
|
||||
--oa-fg-lighter: #ffffff;
|
||||
--oa-fg-darker: #A0A0A0;
|
||||
--oa-fg-darkest: #808080;
|
||||
|
||||
--oa-bg-1: #3655a3;
|
||||
--oa-bg-2: #7a7620;
|
||||
--oa-bg-3: #9f4b1e;
|
||||
--oa-bg-4: #7e1b29;
|
||||
--oa-bg-5: #52628b;
|
||||
--oa-bg-6: #851192;
|
||||
--oa-bg-7: #266b67;
|
||||
--oa-bg-8: #456f2b;
|
||||
|
||||
--oa-fg-1: #7d98de;
|
||||
--oa-fg-2: #ded971;
|
||||
--oa-fg-3: #eda279;
|
||||
--oa-fg-4: #e97d8d;
|
||||
--oa-fg-5: #b1c0e6;
|
||||
--oa-fg-6: #e571f2;
|
||||
--oa-fg-7: #98e6e1;
|
||||
--oa-fg-8: #54b319;
|
||||
|
||||
--oa-bg-tag: var(--oa-bg-1);
|
||||
--oa-fg-tag: var(--oa-fg-lighter);
|
||||
|
||||
--oa-bg-op-get: var(--oa-bg-1);
|
||||
--oa-bg-op-put: var(--oa-bg-2);
|
||||
--oa-bg-op-post: var(--oa-bg-3);
|
||||
--oa-bg-op-delete: var(--oa-bg-4);
|
||||
--oa-bg-op-options: var(--oa-bg-5);
|
||||
--oa-bg-op-head: var(--oa-bg-6);
|
||||
--oa-bg-op-patch: var(--oa-bg-7);
|
||||
--oa-bg-op-trace: var(--oa-bg-8);
|
||||
|
||||
--oa-bg-header: var(--oa-bg-6);
|
||||
--oa-bg-form: var(--oa-bg-7);
|
||||
--oa-bg-path: var(--oa-bg-8);
|
||||
--oa-bg-cookie: var(--oa-bg-1);
|
||||
--oa-bg-query: var(--oa-bg-2);
|
||||
|
||||
--oa-bg-matrix: var(--oa-bg-6);
|
||||
--oa-bg-label: var(--oa-bg-7);
|
||||
--oa-bg-simple: var(--oa-bg-8);
|
||||
--oa-bg-spacedelimited: var(--oa-bg-1);
|
||||
--oa-bg-pipedelimited: var(--oa-bg-2);
|
||||
--oa-bg-deepobject: var(--oa-bg-3);
|
||||
|
||||
--oa-font-small: 12px;
|
||||
--oa-font-smaller: 10px;
|
||||
--oa-font-large: 16px;
|
||||
}
|
||||
11
Demo/App.razor
Normal file
11
Demo/App.razor
Normal file
@ -0,0 +1,11 @@
|
||||
<Router AppAssembly="@typeof(App).Assembly">
|
||||
<Found Context="routeData">
|
||||
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
|
||||
</Found>
|
||||
<NotFound>
|
||||
<PageTitle>Not found</PageTitle>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<p role="alert">Sorry, there's nothing at this address.</p>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
||||
16
Demo/BlazorOpenApi.Demo.csproj
Normal file
16
Demo/BlazorOpenApi.Demo.csproj
Normal file
@ -0,0 +1,16 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MudBlazor" />
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Examples\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BlazorOpenApi\BlazorOpenApi.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
42
Demo/Controllers/TestController.cs
Normal file
42
Demo/Controllers/TestController.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
|
||||
|
||||
namespace BlazorOpenApi.Controllers;
|
||||
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class TestController : ControllerBase
|
||||
{
|
||||
// GET: api/<TestController>
|
||||
[HttpGet]
|
||||
public IEnumerable<string> Get()
|
||||
{
|
||||
return new string[] { "value1", "value2" };
|
||||
}
|
||||
|
||||
// GET api/<TestController>/5
|
||||
[HttpGet("{id}")]
|
||||
public string Get(int id)
|
||||
{
|
||||
return "value";
|
||||
}
|
||||
|
||||
// POST api/<TestController>
|
||||
[HttpPost]
|
||||
public void Post([FromBody] string value)
|
||||
{
|
||||
}
|
||||
|
||||
// PUT api/<TestController>/5
|
||||
[HttpPut("{id}")]
|
||||
public void Put(int id, [FromBody] string value)
|
||||
{
|
||||
}
|
||||
|
||||
// DELETE api/<TestController>/5
|
||||
[HttpDelete("{id}")]
|
||||
public void Delete(int id)
|
||||
{
|
||||
}
|
||||
}
|
||||
1228
Demo/Examples/petstore.yaml
Normal file
1228
Demo/Examples/petstore.yaml
Normal file
File diff suppressed because it is too large
Load Diff
42
Demo/Pages/Error.cshtml
Normal file
42
Demo/Pages/Error.cshtml
Normal file
@ -0,0 +1,42 @@
|
||||
@page
|
||||
@model BlazorOpenApi.Pages.ErrorModel
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<title>Error</title>
|
||||
<link href="~/css/bootstrap/bootstrap.min.css" rel="stylesheet" />
|
||||
<link href="~/css/app.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="main">
|
||||
<div class="content px-4">
|
||||
<h1 class="text-danger">Error.</h1>
|
||||
<h2 class="text-danger">An error occurred while processing your request.</h2>
|
||||
|
||||
@if (Model.ShowRequestId)
|
||||
{
|
||||
<p>
|
||||
<strong>Request ID:</strong> <code>@Model.RequestId</code>
|
||||
</p>
|
||||
}
|
||||
|
||||
<h3>Development Mode</h3>
|
||||
<p>
|
||||
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred.
|
||||
</p>
|
||||
<p>
|
||||
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
|
||||
It can result in displaying sensitive information from exceptions to end users.
|
||||
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
|
||||
and restarting the app.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
26
Demo/Pages/Error.cshtml.cs
Normal file
26
Demo/Pages/Error.cshtml.cs
Normal file
@ -0,0 +1,26 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace BlazorOpenApi.Pages;
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
[IgnoreAntiforgeryToken]
|
||||
public class ErrorModel : PageModel
|
||||
{
|
||||
public string? RequestId { get; set; }
|
||||
|
||||
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
|
||||
|
||||
private readonly ILogger<ErrorModel> _logger;
|
||||
|
||||
public ErrorModel(ILogger<ErrorModel> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void OnGet()
|
||||
{
|
||||
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
|
||||
}
|
||||
}
|
||||
58
Demo/Pages/Index.razor
Normal file
58
Demo/Pages/Index.razor
Normal file
@ -0,0 +1,58 @@
|
||||
@page "/"
|
||||
@inject NavigationManager Navigation
|
||||
|
||||
<PageTitle>Index</PageTitle>
|
||||
@*
|
||||
<MudText Typo="Typo.h3" GutterBottom="true">Hello, world!</MudText>
|
||||
<MudText Class="mb-8">Welcome to your new app, powered by MudBlazor!</MudText>
|
||||
<MudAlert Severity="Severity.Normal">You can find documentation and examples on our website here: <MudLink Href="https://mudblazor.com" Typo="Typo.body2" Color="Color.Inherit"><b>www.mudblazor.com</b></MudLink></MudAlert>
|
||||
|
||||
<MudLink Href="/api-docs/index.html" Typo="Typo.body2" Color="Color.Inherit">/api-docs/index.html</MudLink>
|
||||
*@
|
||||
|
||||
@*
|
||||
<iframe src="/api-docs/index.html" style="width:100%;height:93vh;border:none;" />
|
||||
*@
|
||||
|
||||
<MudList>
|
||||
<MudListItem>
|
||||
<MudLink Href="@(GetUrl("https://redocly.github.io/redoc/openapi.yaml"))">ReDoc version</MudLink>
|
||||
</MudListItem>
|
||||
<MudListItem>
|
||||
<MudLink Href="@(GetUrl("https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.json"))">GitHub version</MudLink>
|
||||
</MudListItem>
|
||||
</MudList>
|
||||
|
||||
<MudCard>
|
||||
<MudForm Model="@model">
|
||||
<MudCardContent>
|
||||
<MudTextField @bind-Value="model.Url"
|
||||
For="@(() => model.Url)"
|
||||
Immediate="true"
|
||||
Label="Url" />
|
||||
|
||||
</MudCardContent>
|
||||
</MudForm>
|
||||
<MudCardActions>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary" Class="ml-auto" OnClick="@Submit">Display</MudButton>
|
||||
</MudCardActions>
|
||||
</MudCard>
|
||||
|
||||
@code {
|
||||
|
||||
private static string GetUrl(string url) => "openapi-ui?url=" + Uri.UnescapeDataString(url);
|
||||
|
||||
UrlModel model = new UrlModel();
|
||||
|
||||
public class UrlModel
|
||||
{
|
||||
public string Url { get; set; } = "";
|
||||
}
|
||||
|
||||
private Task Submit()
|
||||
{
|
||||
Navigation.NavigateTo(GetUrl(model.Url));
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
}
|
||||
25
Demo/Pages/OpenApiUI.razor
Normal file
25
Demo/Pages/OpenApiUI.razor
Normal file
@ -0,0 +1,25 @@
|
||||
@page "/openapi-ui"
|
||||
|
||||
@using BlazorOpenApi;
|
||||
|
||||
<PageTitle>OpenApiUI</PageTitle>
|
||||
|
||||
@* <OpenAPIUIControl Url="@Url" Palette="@TestPalette"/> *@
|
||||
<OpenAPIUIControl Url="@Url" />
|
||||
|
||||
@code {
|
||||
[Parameter]
|
||||
[SupplyParameterFromQuery(Name = "url")]
|
||||
public string Url { get; set; } = "https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.json";
|
||||
|
||||
// private OpenApiUiPalette TestPalette
|
||||
// {
|
||||
// get
|
||||
// {
|
||||
// var p = new OpenApiUiPalette().Clone();
|
||||
// p.Foreground[7] = "blue";
|
||||
|
||||
// return p;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
8
Demo/Pages/_Host.cshtml
Normal file
8
Demo/Pages/_Host.cshtml
Normal file
@ -0,0 +1,8 @@
|
||||
@page "/"
|
||||
@namespace BlazorOpenApi.Demo.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
@{
|
||||
Layout = "_Layout";
|
||||
}
|
||||
|
||||
<component type="typeof(App)" render-mode="ServerPrerendered" />
|
||||
32
Demo/Pages/_Layout.cshtml
Normal file
32
Demo/Pages/_Layout.cshtml
Normal file
@ -0,0 +1,32 @@
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@namespace BlazorOpenApi.Pages
|
||||
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<base href="~/" />
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" rel="stylesheet" />
|
||||
<link href="_content/BlazorOpenApi/css/openapi-ui.css" rel="stylesheet" />
|
||||
<link href="_content/MudBlazor/MudBlazor.min.css" rel="stylesheet" />
|
||||
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
|
||||
</head>
|
||||
<body>
|
||||
@RenderBody()
|
||||
|
||||
<div id="blazor-error-ui">
|
||||
<environment include="Staging,Production">
|
||||
An error has occurred. This application may no longer respond until reloaded.
|
||||
</environment>
|
||||
<environment include="Development">
|
||||
An unhandled exception has occurred. See browser dev tools for details.
|
||||
</environment>
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss">🗙</a>
|
||||
</div>
|
||||
<script src="_framework/blazor.server.js"></script>
|
||||
<script src="_content/MudBlazor/MudBlazor.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
45
Demo/Program.cs
Normal file
45
Demo/Program.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using Microsoft.AspNetCore.Hosting.StaticWebAssets;
|
||||
using MudBlazor.Services;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
StaticWebAssetsLoader.UseStaticWebAssets(builder.Environment, builder.Configuration);
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddRazorPages();
|
||||
builder.Services.AddServerSideBlazor();
|
||||
builder.Services.AddMudServices();
|
||||
|
||||
builder.Services.AddControllers();
|
||||
//builder.Services.AddSwaggerGen(c =>
|
||||
//{
|
||||
// c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
|
||||
//});
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
if (!app.Environment.IsDevelopment())
|
||||
{
|
||||
app.UseExceptionHandler("/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.UseRouting();
|
||||
//app.UseSwagger();
|
||||
|
||||
//app.UseReDoc(c =>
|
||||
//{
|
||||
// c.DocumentTitle = "REDOC API Documentation";
|
||||
// c.SpecUrl = "/swagger/v1/swagger.json";
|
||||
//});
|
||||
|
||||
app.MapBlazorHub();
|
||||
app.MapFallbackToPage("/_Host");
|
||||
|
||||
app.Run();
|
||||
22
Demo/Properties/launchSettings.json
Normal file
22
Demo/Properties/launchSettings.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"profiles": {
|
||||
"BlazorOpenApi": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "http://localhost:5000/openapi-ui?url=https://redocly.github.io/redoc/openapi.yaml",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"dotnetRunMessages": true,
|
||||
"applicationUrl": "http://localhost:5000"
|
||||
}
|
||||
},
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:61949",
|
||||
"sslPort": 44393
|
||||
}
|
||||
}
|
||||
}
|
||||
6
Demo/README.md
Normal file
6
Demo/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# Blazor OpenAPI UI Demo
|
||||
|
||||
Shows capabilities of `BlazorOpenApi`.
|
||||
|
||||
|
||||
|
||||
55
Demo/Shared/MainLayout.razor
Normal file
55
Demo/Shared/MainLayout.razor
Normal file
@ -0,0 +1,55 @@
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<MudThemeProvider @ref="@_mudThemeProvider" @bind-IsDarkMode="@IsDarkMode" />
|
||||
<MudDialogProvider />
|
||||
<MudSnackbarProvider />
|
||||
|
||||
<MudLayout>
|
||||
<MudAppBar Elevation="0">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@((e) => DrawerToggle())" />
|
||||
<MudSpacer />
|
||||
<MudIconButton Icon="@Icons.Custom.Brands.MudBlazor" Color="Color.Inherit" Href="https://mudblazor.com/" Target="_blank" />
|
||||
<MudIconButton Icon="@Icons.Custom.Brands.GitHub" Color="Color.Inherit" Href="https://github.com/MudBlazor/MudBlazor/" Target="_blank" />
|
||||
</MudAppBar>
|
||||
<MudDrawer @bind-Open="_drawerOpen" Elevation="1">
|
||||
<MudDrawerHeader>
|
||||
<MudText Typo="Typo.h6">OpenApiUI Demo</MudText>
|
||||
</MudDrawerHeader>
|
||||
<NavMenu />
|
||||
<div class="d-flex justify-left align-end mud-height-full">
|
||||
<MudSwitch @bind-Value="@IsDarkMode" Color="MudBlazor.Color.Primary" Class="ma-4" T="bool" Label="Dark Mode" />
|
||||
</div>
|
||||
</MudDrawer>
|
||||
<MudMainContent>
|
||||
<CascadingValue Value="@IsDarkMode">
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraExtraLarge" Class="pt-2">
|
||||
@Body
|
||||
</MudContainer>
|
||||
</CascadingValue>
|
||||
</MudMainContent>
|
||||
</MudLayout>
|
||||
|
||||
@code {
|
||||
bool _drawerOpen = true;
|
||||
private bool IsDarkMode;
|
||||
private MudThemeProvider? _mudThemeProvider;
|
||||
|
||||
void DrawerToggle() => _drawerOpen = !_drawerOpen;
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
IsDarkMode = await _mudThemeProvider!.GetSystemPreference();
|
||||
await _mudThemeProvider.WatchSystemPreference(OnSystemPreferenceChanged);
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnSystemPreferenceChanged(bool newValue)
|
||||
{
|
||||
IsDarkMode = newValue;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
}
|
||||
28
Demo/Shared/NavMenu.razor
Normal file
28
Demo/Shared/NavMenu.razor
Normal file
@ -0,0 +1,28 @@
|
||||
<MudNavMenu>
|
||||
<MudNavLink Href="" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Home">Home</MudNavLink>
|
||||
|
||||
<MudNavLink Href="@(GetUrl("https://redocly.github.io/redoc/openapi.yaml"))"
|
||||
Match="NavLinkMatch.All"
|
||||
Icon="@Icons.Material.Filled.Abc">
|
||||
ReDoc version
|
||||
</MudNavLink>
|
||||
<MudNavLink Href="@(GetUrl("https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/examples/v3.0/petstore.json"))"
|
||||
Match="NavLinkMatch.All"
|
||||
Icon="@Icons.Material.Filled.AccountBox">
|
||||
GitHub version
|
||||
</MudNavLink>
|
||||
<MudNavLink Href="@(GetUrl("https://dtrnk0o2zy01c.cloudfront.net/openapi/en-us/dest/BrandMetrics_prod_3p.json"))"
|
||||
Match="NavLinkMatch.All"
|
||||
Icon="@Icons.Material.Filled.Cloud">
|
||||
Amazon Brand Metrics
|
||||
</MudNavLink>
|
||||
<MudNavLink Href="@(GetUrl("https://learn.microsoft.com/en-us/dynamics365/business-central/dev-itpro/api-reference/v1.0/contracts/bcoas1.0.yaml"))"
|
||||
Match="NavLinkMatch.All"
|
||||
Icon="@Icons.Material.Filled.Cloud">
|
||||
Dynamics 365 BC
|
||||
</MudNavLink>
|
||||
</MudNavMenu>
|
||||
|
||||
@code {
|
||||
private static string GetUrl(string url) => "openapi-ui?url=" + Uri.UnescapeDataString(url);
|
||||
}
|
||||
13
Demo/_Imports.razor
Normal file
13
Demo/_Imports.razor
Normal file
@ -0,0 +1,13 @@
|
||||
@using System.Net.Http
|
||||
@using Microsoft.AspNetCore.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Authorization
|
||||
@using Microsoft.AspNetCore.Components.Forms
|
||||
@using Microsoft.AspNetCore.Components.Routing
|
||||
@using Microsoft.AspNetCore.Components.Web
|
||||
@using Microsoft.AspNetCore.Components.Web.Virtualization
|
||||
@using Microsoft.JSInterop
|
||||
@using MudBlazor
|
||||
@using BlazorOpenApi
|
||||
@using BlazorOpenApi.Controls
|
||||
@using BlazorOpenApi.Demo
|
||||
@using BlazorOpenApi.Demo.Shared
|
||||
10
Demo/appsettings.Development.json
Normal file
10
Demo/appsettings.Development.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"DetailedErrors": true,
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
}
|
||||
10
Demo/appsettings.json
Normal file
10
Demo/appsettings.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
}
|
||||
BIN
Demo/wwwroot/favicon.ico
Normal file
BIN
Demo/wwwroot/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
8
Directory.Build.props
Normal file
8
Directory.Build.props
Normal file
@ -0,0 +1,8 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<LangVersion>preview</LangVersion>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
13
Directory.Packages.props
Normal file
13
Directory.Packages.props
Normal file
@ -0,0 +1,13 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageVersion Include="MudBlazor" Version="8.3.0" />
|
||||
<PackageVersion Include="Markdig" Version="0.40.0" />
|
||||
<PackageVersion Include="Microsoft.OpenApi.Readers" Version="2.0.0-preview9" />
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore.ReDoc" Version="6.5.0" />
|
||||
<PackageVersion Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.5.0" />
|
||||
<PackageVersion Include="System.Text.Json" Version="9.0.2" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Loading…
x
Reference in New Issue
Block a user