diff --git a/samples/build-tools/build-scripts/BuildAppSettings.cs b/samples/build-tools/build-scripts/BuildAppSettings.cs index b0ea8c7..7cc7c8e 100644 --- a/samples/build-tools/build-scripts/BuildAppSettings.cs +++ b/samples/build-tools/build-scripts/BuildAppSettings.cs @@ -8,7 +8,6 @@ // -k, --api-key ArcGIS API key (required) // -l, --license-key GeoBlazor license key (required) // -o, --output Output path(s) for appsettings.json (required, can specify multiple) -// -d, --docs-url Documentation URL (default: https://docs.geoblazor.com) // -b, --bypass-key API bypass key for samples (optional) // -w, --wfs-servers Additional WFS server configuration JSON fragment (optional) // -h, --help Display help message @@ -22,7 +21,6 @@ string? arcGISApiKey = null; string? licenseKey = null; List outputPaths = []; -string docsUrl = "https://docs.geoblazor.com"; string byPassApiKey = ""; string wfsServers = ""; bool help = false; @@ -54,13 +52,6 @@ outputPaths.Add(args[++i]); } break; - case "-d": - case "--docs-url": - if (i + 1 < args.Length) - { - docsUrl = args[++i]; - } - break; case "-b": case "--bypass-key": if (i + 1 < args.Length) @@ -93,7 +84,6 @@ Console.WriteLine(" -k, --api-key ArcGIS API key (required)"); Console.WriteLine(" -l, --license-key GeoBlazor license key (required)"); Console.WriteLine(" -o, --output Output path(s) for appsettings.json (required, can specify multiple)"); - Console.WriteLine(" -d, --docs-url Documentation URL (default: https://docs.geoblazor.com)"); Console.WriteLine(" -b, --bypass-key API bypass key for samples (optional)"); Console.WriteLine(" -w, --wfs-servers Additional WFS server configuration JSON fragment (optional)"); Console.WriteLine(" -h, --help Display this help message"); @@ -130,7 +120,6 @@ sb.AppendLine(" \"GeoBlazor\": {"); sb.AppendLine($" \"LicenseKey\": \"{EscapeJsonString(licenseKey)}\""); sb.AppendLine(" },"); -sb.AppendLine($" \"DocsUrl\": \"{EscapeJsonString(docsUrl)}\","); sb.Append($" \"ByPassApiKey\": \"{EscapeJsonString(byPassApiKey)}\""); // Add WFS servers if provided diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Maui/MauiProgram.cs b/samples/core/dymaptic.GeoBlazor.Core.Sample.Maui/MauiProgram.cs index e371711..5bec05f 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Maui/MauiProgram.cs +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Maui/MauiProgram.cs @@ -38,6 +38,7 @@ public static MauiApp CreateMauiApp() builder.Configuration.AddConfiguration(config); builder.Services.AddGeoBlazor(builder.Configuration); builder.Services.AddScoped(); + builder.Services.AddSingleton(); return builder.Build(); } diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SourceCode.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SourceCode.razor similarity index 64% rename from samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SourceCode.razor rename to samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SourceCode.razor index eecf9ac..4abb9b3 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SourceCode.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SourceCode.razor @@ -1,10 +1,14 @@ -@page "/source-code" +@page "/source-code" @page "/source-code/{PageUrl}" Source Code

Source Code

-@if (string.IsNullOrWhiteSpace(_razorContent)) +@if (_notFound) +{ +

Source for @PageUrl is not embedded in the sample app.

+} +else if (string.IsNullOrWhiteSpace(_razorContent)) {

Loading...

} @@ -15,4 +19,4 @@ else { } -} \ No newline at end of file +} diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SourceCode.razor.cs b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SourceCode.razor.cs new file mode 100644 index 0000000..9392279 --- /dev/null +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SourceCode.razor.cs @@ -0,0 +1,109 @@ +using System.Reflection; +using dymaptic.GeoBlazor.Core.Sample.Shared.Shared; +using Microsoft.AspNetCore.Components; + +namespace dymaptic.GeoBlazor.Core.Sample.Shared.Pages; + +public partial class SourceCode +{ + [Parameter] + public string? PageUrl { get; set; } + + [Inject] + public required ISampleSourceProvider SourceProvider { get; set; } + + protected override void OnParametersSet() + { + if (string.IsNullOrWhiteSpace(PageUrl)) + { + _razorContent = string.Empty; + _codeContent = string.Empty; + _notFound = false; + return; + } + + Type? pageType = ResolvePageType(PageUrl); + if (pageType is null) + { + _razorContent = string.Empty; + _codeContent = string.Empty; + _notFound = true; + return; + } + + (string razor, string? codeBehind) = SourceProvider.GetSource(pageType); + + if (string.IsNullOrEmpty(razor)) + { + _razorContent = string.Empty; + _codeContent = string.Empty; + _notFound = true; + return; + } + + _notFound = false; + + // split apart the markup section and the code section so the highlighting can be language-specific + // for HTML and C#, since there is no widely accepted Razor syntax highlighting + if (razor.Contains("@code")) + { + int codeIndex = razor.IndexOf("@code", StringComparison.Ordinal); + _codeContent = razor[codeIndex..].Trim(); + _razorContent = razor[..codeIndex].Trim(); + } + else + { + _razorContent = razor; + _codeContent = string.Empty; + } + + if (!string.IsNullOrEmpty(codeBehind)) + { + _razorContent = $""" + ## {PageUrl}.razor + + {_razorContent} + """; + _codeContent = $""" + ## {PageUrl}.razor.cs + + {codeBehind} + """; + } + } + + private static Type? ResolvePageType(string typeName) + { + Dictionary index = LazyPageIndex.Value; + return index.TryGetValue(typeName, out Type? t) ? t : null; + } + + private static readonly Lazy> LazyPageIndex = new(() => + { + var index = new Dictionary(StringComparer.Ordinal); + foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + string? name = assembly.GetName().Name; + if (name is null) continue; + if (!name.Contains("Sample.Shared", StringComparison.Ordinal)) continue; + + Type[] types; + try { types = assembly.GetExportedTypes(); } + catch { continue; } + + foreach (Type type in types) + { + if (type.GetCustomAttributes().Any()) + { + // last writer wins; Pro can shadow Core if names collide + index[type.Name] = type; + } + } + } + return index; + }); + + private string _razorContent = string.Empty; + private string _codeContent = string.Empty; + private bool _notFound; +} diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SourceCode.razor.css b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SourceCode.razor.css similarity index 100% rename from samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SourceCode.razor.css rename to samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SourceCode.razor.css diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor index f3408a1..0a3dc49 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor @@ -72,7 +72,7 @@ } protected virtual Type NavMenuType => typeof(NavMenu); - protected virtual Type? AdditionalLinksType => null; + protected virtual Type? AdditionalLinksType => typeof(SourceNav); private readonly string[] _btnTypes = ["btn-primary", "btn-secondary", "btn-accent"]; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/SampleSourceProvider.cs b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/SampleSourceProvider.cs new file mode 100644 index 0000000..781550f --- /dev/null +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/SampleSourceProvider.cs @@ -0,0 +1,27 @@ +using System.Reflection; + +namespace dymaptic.GeoBlazor.Core.Sample.Shared.Shared; + +public interface ISampleSourceProvider +{ + (string Razor, string? CodeBehind) GetSource(Type pageType); +} + +public class SampleSourceProvider : ISampleSourceProvider +{ + public (string Razor, string? CodeBehind) GetSource(Type pageType) + { + Assembly assembly = pageType.Assembly; + string razor = ReadResource(assembly, $"SampleSource/{pageType.Name}.razor") ?? string.Empty; + string? codeBehind = ReadResource(assembly, $"SampleSource/{pageType.Name}.razor.cs"); + return (razor, codeBehind); + } + + private static string? ReadResource(Assembly assembly, string logicalName) + { + using Stream? stream = assembly.GetManifestResourceStream(logicalName); + if (stream is null) return null; + using var reader = new StreamReader(stream); + return reader.ReadToEnd(); + } +} diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Shared/SourceNav.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/SourceNav.razor similarity index 98% rename from samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Shared/SourceNav.razor rename to samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/SourceNav.razor index c3f53b1..efb83b8 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Shared/SourceNav.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/SourceNav.razor @@ -7,10 +7,10 @@ GitHub
Repo
@code { - + [Inject] public required NavigationManager NavigationManager { get; set; } - + [CascadingParameter(Name="PageRouteData")] public required RouteData RouteData { get; set; } @@ -25,4 +25,4 @@ NavigationManager.NavigateTo("https://github.com/dymaptic/GeoBlazor"); } -} \ No newline at end of file +} diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/dymaptic.GeoBlazor.Core.Sample.Shared.csproj b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/dymaptic.GeoBlazor.Core.Sample.Shared.csproj index 61e2150..ad70d2a 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/dymaptic.GeoBlazor.Core.Sample.Shared.csproj +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/dymaptic.GeoBlazor.Core.Sample.Shared.csproj @@ -42,4 +42,9 @@ + + + + + diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Wasm/Program.cs b/samples/core/dymaptic.GeoBlazor.Core.Sample.Wasm/Program.cs index 42c26ea..d492ad0 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Wasm/Program.cs +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Wasm/Program.cs @@ -11,6 +11,7 @@ builder.Services.AddGeoBlazor(builder.Configuration); builder.Services.AddScoped(); +builder.Services.AddSingleton(); builder.Configuration.AddInMemoryCollection(); builder.Services.AddScoped(); diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.Client/Program.cs b/samples/core/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.Client/Program.cs index b14dd83..390dda0 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.Client/Program.cs +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp.Client/Program.cs @@ -9,5 +9,6 @@ builder.Services.AddGeoBlazor(builder.Configuration); builder.Services.AddSingleton(_ => builder.Configuration); builder.Services.AddScoped(); +builder.Services.AddSingleton(); await builder.Build().RunAsync(); \ No newline at end of file diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp/Program.cs b/samples/core/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp/Program.cs index 8c31f1d..8d4df96 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp/Program.cs +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.WebApp/dymaptic.GeoBlazor.Core.Sample.WebApp/Program.cs @@ -14,6 +14,7 @@ builder.Services.AddGeoBlazor(builder.Configuration); builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddSingleton(); builder.Configuration.AddInMemoryCollection(); WebApplication app = builder.Build(); diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Maui/MauiProgram.cs b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Maui/MauiProgram.cs index 1000fef..7c7d759 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Maui/MauiProgram.cs +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Maui/MauiProgram.cs @@ -38,6 +38,7 @@ public static MauiApp CreateMauiApp() builder.Configuration.AddConfiguration(config); builder.Services.AddGeoBlazorPro(builder.Configuration); builder.Services.AddScoped(); + builder.Services.AddSingleton(); return builder.Build(); } diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SourceCode.razor.cs b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SourceCode.razor.cs deleted file mode 100644 index 1787527..0000000 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SourceCode.razor.cs +++ /dev/null @@ -1,79 +0,0 @@ -using Microsoft.AspNetCore.Components; -using Microsoft.Extensions.Configuration; -using Microsoft.JSInterop; - - -namespace dymaptic.GeoBlazor.Pro.Sample.Shared.Pages; - -public partial class SourceCode -{ - [Parameter] - public string? PageUrl { get; set; } - [Inject] - public required HttpClient HttpClient { get; set; } - [Inject] - public required IJSRuntime JsRuntime { get; set; } - [Inject] - public required IConfiguration Configuration { get; set; } - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - await base.OnAfterRenderAsync(firstRender); - - if (PageUrl is null) - { - PageUrl = string.Empty; - - return; - } - - if (firstRender) - { - string docsUrl = Configuration["DocsUrl"] ?? "https://docs.geoblazor.com"; - HttpClient.BaseAddress ??= new Uri(docsUrl); - string pageUrl = $"assets/samples/{PageUrl}.razor.txt"; - _razorContent = await HttpClient.GetStringAsync(pageUrl); - - // split apart the markup section and the code section so the highlighting can be language-specific - // for HTML and C#, since there is no widely accepted Razor syntax highlighting - if (_razorContent.Contains("@code")) - { - int codeIndex = _razorContent.IndexOf("@code", StringComparison.Ordinal); - _codeContent = _razorContent[codeIndex..].Trim(); - _razorContent = _razorContent[..codeIndex].Trim(); - } - - // check for code-behind file - pageUrl = $"assets/samples/{PageUrl}.razor.cs.txt"; - - try - { - HttpResponseMessage result = await HttpClient.GetAsync(pageUrl); - - if (result.IsSuccessStatusCode) - { - _codeContent = $""" - ## {PageUrl}.razor.cs - - {await result.Content.ReadAsStringAsync()} - """; - - _razorContent = $""" - ## {PageUrl}.razor - - {_razorContent} - """; - } - } - catch - { - // ignore - } - - StateHasChanged(); - } - } - - private string _razorContent = string.Empty; - private string _codeContent = string.Empty; -} \ No newline at end of file diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/dymaptic.GeoBlazor.Pro.Sample.Shared.csproj b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/dymaptic.GeoBlazor.Pro.Sample.Shared.csproj index 4a855d1..d091623 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/dymaptic.GeoBlazor.Pro.Sample.Shared.csproj +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/dymaptic.GeoBlazor.Pro.Sample.Shared.csproj @@ -38,4 +38,9 @@ + + + + + diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Wasm/Program.cs b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Wasm/Program.cs index 6a76ed0..b58fa15 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Wasm/Program.cs +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Wasm/Program.cs @@ -14,5 +14,6 @@ builder.Services.AddGeoBlazorPro(builder.Configuration); builder.Services.AddScoped(); +builder.Services.AddSingleton(); await builder.Build().RunAsync(); \ No newline at end of file diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.WebApp/dymaptic.GeoBlazor.Pro.Sample.WebApp.Client/Program.cs b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.WebApp/dymaptic.GeoBlazor.Pro.Sample.WebApp.Client/Program.cs index 8c0c55f..ad16872 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.WebApp/dymaptic.GeoBlazor.Pro.Sample.WebApp.Client/Program.cs +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.WebApp/dymaptic.GeoBlazor.Pro.Sample.WebApp.Client/Program.cs @@ -8,6 +8,7 @@ builder.Services.AddScoped(); builder.Services.AddGeoBlazorPro(builder.Configuration); builder.Services.AddScoped(); +builder.Services.AddSingleton(); builder.Services.AddSingleton(_ => builder.Configuration); await builder.Build().RunAsync(); \ No newline at end of file diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.WebApp/dymaptic.GeoBlazor.Pro.Sample.WebApp/Program.cs b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.WebApp/dymaptic.GeoBlazor.Pro.Sample.WebApp/Program.cs index ff78a27..9fa989a 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.WebApp/dymaptic.GeoBlazor.Pro.Sample.WebApp/Program.cs +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.WebApp/dymaptic.GeoBlazor.Pro.Sample.WebApp/Program.cs @@ -18,6 +18,7 @@ builder.Services.AddGeoBlazorPro(builder.Configuration); builder.Services.AddScoped(); +builder.Services.AddSingleton(); builder.Configuration.AddInMemoryCollection(); builder.Services.AddOutputCache(); builder.Services.AddMemoryCache(); diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.WebApp/dymaptic.GeoBlazor.Pro.Sample.WebApp/appsettings.Development.json b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.WebApp/dymaptic.GeoBlazor.Pro.Sample.WebApp/appsettings.Development.json index 66551d3..26db8bd 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.WebApp/dymaptic.GeoBlazor.Pro.Sample.WebApp/appsettings.Development.json +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.WebApp/dymaptic.GeoBlazor.Pro.Sample.WebApp/appsettings.Development.json @@ -8,7 +8,6 @@ "Polly": "Debug" } }, - "DocsUrl": "http://127.0.0.1:4000", "GeoBlazor": { "Theme": "Dark" }