From a1b011ec2c5313bcf9bed72e626677eea8fb30f1 Mon Sep 17 00:00:00 2001 From: Maggie Moeller Date: Tue, 31 Mar 2026 13:37:38 -0400 Subject: [PATCH 1/7] Add Legend and GeoJSON samples, fix dark mode styling New Core samples: - Legend: Toggleable layers with LegendWidget, responsive side-by-side layout - GeoJSON Layers: USGS earthquake data with size variable renderer and popups Styling fixes: - Fix esri-widget dark mode background (was white, now matches site theme) - Fix inline code readability (was orange-red on black, now green on dark gray) Bug fix: - Fix UniqueValueRenderers build error (missing ToUpperFirstChar extension) Co-Authored-By: Claude Opus 4.6 (1M context) --- .../Pages/GeoJSONLayers.razor | 126 +++++++++++++++++ .../Pages/Legends.razor | 132 ++++++++++++++++++ .../Pages/UniqueValueRenderers.razor.cs | 2 +- .../Shared/NavMenu.razor.cs | 2 + .../wwwroot/css/site.css | 3 +- .../wwwroot/images/geojson.svg | 10 ++ .../wwwroot/images/legend.svg | 17 +++ 7 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeoJSONLayers.razor create mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Legends.razor create mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/images/geojson.svg create mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/images/legend.svg diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeoJSONLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeoJSONLayers.razor new file mode 100644 index 0000000..156d246 --- /dev/null +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeoJSONLayers.razor @@ -0,0 +1,126 @@ +@page "/geojson-layers" + +GeoJSON Layers +

GeoJSON Layers

+ + +

+ Load GeoJSON data directly from a URL. Toggle the checkbox to display recent earthquake data from the USGS, + styled by magnitude with an interactive popup. Click any earthquake to see its details. +

+ +
+
+
+ +
+
+ +
+
+ Data: USGS Earthquake Hazards Program +
+
+ + + + + + + + @if (_showEarthquakes) + { + + + + + + + + + + } + + + +
+ + + +@code { + private bool _showEarthquakes; + private string _dataUrl = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson"; + + private void OnSourceChanged(ChangeEventArgs e) + { + string period = e.Value?.ToString() ?? "month"; + _dataUrl = period switch + { + "week" => "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson", + "day" => "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson", + _ => "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson" + }; + } +} diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Legends.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Legends.razor new file mode 100644 index 0000000..feaa308 --- /dev/null +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Legends.razor @@ -0,0 +1,132 @@ +@page "/legends" + +Legend +

Legend

+ + +

+ The Legend widget describes the symbols used to represent layers in the map. Enable the layers + to see the legend populate automatically. The legend reflects each layer's renderer and symbology. +

+ +
+
+
+ +
+
+ +
+
+ +
+
+ + + + + + + + @if (_showCensusLayer) + { + + + + + + + + + } + + @if (_showTrailsLayer) + { + + + + + + + + + + + } + + @if (_showParksLayer) + { + + + + + + + + } + + + + +
+ + + +@code { + private bool _showCensusLayer; + private bool _showTrailsLayer; + private bool _showParksLayer; + private FeatureLayer? _censusLayer; +} diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/UniqueValueRenderers.razor.cs b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/UniqueValueRenderers.razor.cs index a21a830..ebd0251 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/UniqueValueRenderers.razor.cs +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/UniqueValueRenderers.razor.cs @@ -60,7 +60,7 @@ public partial class UniqueValueRenderers ["proposed"] = new SimpleLineSymbol(new MapColor(192, 192, 192), 1.5, SimpleLineSymbolStyle.Dot) }; private readonly UniqueValueRenderer _uniqueValueRenderer = new(uniqueValueInfos: roadTypes - .Select(r => new UniqueValueInfo(r.Key.ToUpperFirstChar().Replace("_", " "), r.Value, r.Key)) + .Select(r => new UniqueValueInfo(string.Concat(r.Key[0].ToString().ToUpper(), r.Key.AsSpan(1)).Replace("_", " "), r.Value, r.Key)) .ToArray(), field: "highway", defaultLabel: "Service", legendOptions: new UniqueValueRendererLegendOptions("Route Type")); diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/NavMenu.razor.cs b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/NavMenu.razor.cs index b9a85f5..0853050 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/NavMenu.razor.cs +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/NavMenu.razor.cs @@ -102,6 +102,7 @@ await InvokeAsync(async () => new("basemap-layer-lists", "Basemap Layer Lists", "oi-spreadsheet"), new("csv-layer", "CSV Layers", "oi-grid-four-up"), new("kmllayers", "KML Layers", "oi-excerpt"), + new("geojson-layers", "GeoJSON Layers", null, "geojson.svg"), new("georss-layer", "GeoRSS Layer", "oi-rss"), new("osm-layer", "OpenStreetMaps Layer", null, "osm.webp"), new("wcslayers", "WCS Layers", "oi-project"), @@ -127,6 +128,7 @@ await InvokeAsync(async () => new("projection", "Display Projection", "oi-sun"), new("projection-tool", "Projection Tool", "oi-cog"), new("basemap-projections", "Basemap Projections", "oi-bullhorn"), + new("legends", "Legend", null, "legend.svg"), new("unique-value", "Unique Renderers", "oi-eyedropper"), new("marker-rotation", "Marker Rotation", "oi-loop-circular"), new("graphic-tracking", "Graphic Tracking", "oi-move"), diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/css/site.css b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/css/site.css index fd39ef2..1ca6262 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/css/site.css +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/css/site.css @@ -32,7 +32,8 @@ summary a { } .esri-widget:not(.esri-feature-table) { - color: unset; + color: var(--text-emphasis); + background-color: var(--background-grey-2); } .esri-button { diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/images/geojson.svg b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/images/geojson.svg new file mode 100644 index 0000000..465a873 --- /dev/null +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/images/geojson.svg @@ -0,0 +1,10 @@ + + + + { + } + + + + + diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/images/legend.svg b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/images/legend.svg new file mode 100644 index 0000000..5c925af --- /dev/null +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/wwwroot/images/legend.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + From dcd96b172119bd2c21e4dd50cdb897eefff4c4f6 Mon Sep 17 00:00:00 2001 From: Tim Purdum Date: Thu, 23 Apr 2026 23:05:47 -0500 Subject: [PATCH 2/7] Testing and restyling --- .../MauiProgram.cs | 2 + .../Components/RenderModeSelector.razor.css | 6 + .../Pages/BasemapProjections.razor | 10 +- .../Pages/Basemaps.razor | 110 ++--- .../Pages/Basemaps.razor.css | 14 - .../Pages/BasemapsLayerLists.razor | 33 +- .../Pages/Bookmarks.razor | 12 +- .../Pages/CSVLayers.razor | 81 +++- .../Pages/CalculateGeometries.razor | 11 +- .../Pages/ClickToAdd.razor | 16 +- .../Pages/DisplayProjection.razor | 14 +- .../Pages/Drawing.razor | 242 +++++------ .../Pages/Drawing.razor.css | 33 -- .../Pages/Events.razor | 259 ++++++------ .../Pages/Events.razor.css | 46 -- .../Pages/FeatureLayers.razor | 64 +-- .../Pages/FeatureLayers.razor.css | 3 - .../Pages/GeoJSONLayers.razor | 147 +++---- .../Pages/GeoRSSLayers.razor | 14 +- .../Pages/GraphicTracking.razor | 11 +- .../Pages/HitTests.razor | 11 +- .../Pages/ImageryLayers.razor | 31 +- .../Pages/ImageryTileLayers.razor | 13 +- .../Pages/KMLLayers.razor | 31 +- .../Pages/Labels.razor | 16 +- .../Pages/LayerLists.razor | 11 +- .../Pages/Legends.razor | 91 ++-- .../Pages/ManyGraphics.razor | 48 ++- .../Pages/MapImageLayers.razor | 138 +++--- .../Pages/MapImageLayers.razor.css | 20 +- .../Pages/MarkerRotation.razor | 14 +- .../Pages/MeasurementWidgets.razor | 13 +- .../Pages/Navigation.razor | 29 +- .../Pages/Navigation.razor.css | 10 - .../Pages/OpenStreetMapsLayers.razor | 14 +- .../Pages/PlaceSelector.razor | 12 +- .../Pages/PopupActions.razor | 12 +- .../Pages/Popups.razor | 52 +-- .../Pages/ProjectionTool.Razor.css | 28 -- .../Pages/ProjectionTool.razor | 175 +++++--- .../Pages/QueryRelatedFeatures.razor | 11 +- .../Pages/QueryTopFeatures.razor | 11 +- .../Pages/ReactiveUtils.razor | 319 +++++++------- .../Pages/ReactiveUtils.razor.css | 38 -- .../Pages/ReverseGeolocator.razor | 12 +- .../Pages/Scene.razor | 43 +- .../Pages/SearchMultipleSources.razor | 16 +- .../Pages/ServerSideQueries.razor | 13 +- .../Pages/ServiceAreas.razor | 9 +- .../Pages/SqlFilterQuery.razor | 12 +- .../Pages/SqlQuery.razor | 12 +- .../Pages/UniqueValueRenderers.razor | 7 +- .../Pages/UniqueValueRenderers.razor.cs | 9 +- .../Pages/VectorLayer.razor | 14 +- .../Pages/WCSLayers.razor | 11 +- .../Pages/WFSLayers.razor | 14 +- .../Pages/WMSLayers.razor | 16 +- .../Pages/WMTSLayers.razor | 12 +- .../Pages/WebMaps.razor | 9 +- .../Pages/WebScenes.razor | 14 +- .../Pages/Widgets.razor | 91 ++-- .../Pages/Widgets.razor.css | 22 +- .../Shared/Accordion.razor | 20 + .../Shared/Accordion.razor.css | 12 + .../Shared/LayoutService.cs | 14 + .../Shared/MainLayout.razor | 151 +++---- .../Shared/MainLayout.razor.css | 94 +++-- .../Shared/NavMenu.razor | 2 +- .../Shared/NavMenu.razor.cs | 2 +- .../Shared/RadioGroup.razor | 33 ++ .../Shared/RadioGroup.razor.css | 38 ++ .../Shared/RadioRow.razor | 66 +++ .../Shared/RadioRow.razor.css | 21 + .../Shared/SamplePage.cs | 17 + .../_Imports.razor | 1 + .../wwwroot/css/site.css | 394 ++++++++++++++---- .../wwwroot/images/legend.svg | 6 +- .../Program.cs | 2 + .../Program.cs | 2 + .../Components/App.razor | 2 +- .../Program.cs | 1 + .../MauiProgram.cs | 2 + .../Pages/ApplyEdits.razor | 11 +- .../Pages/Binning.razor | 17 +- .../Pages/ClusterPieCharts.razor | 21 +- .../Pages/Clustering.razor | 17 +- .../Pages/ClusteringPopups.razor | 14 +- .../Pages/CustomPopupContents.razor | 5 +- .../Pages/CustomPopupContents.razor.cs | 7 + .../Pages/DemographicData.razor | 11 +- .../Pages/EditFeatureData.razor | 11 +- .../Pages/GroupLayers.razor | 11 +- .../Pages/HighlightFeaturesByGeometry.razor | 14 +- .../Pages/ImageryGroupBlend.razor | 11 +- .../Pages/LengthAndArea.razor | 11 +- .../Pages/OGCFeatureLayers.razor | 11 +- .../Pages/PopupEdit.razor | 12 +- .../Pages/PrintWidgets.razor | 11 +- .../Pages/ProBookmarks.razor | 12 +- .../Pages/ProWidgets.razor | 217 ++++++---- .../Pages/ProWidgets.razor.css | 22 +- .../Pages/RoutesAndDirections.razor | 12 +- .../Pages/SearchCustomSource.razor | 11 +- .../Pages/SketchQuery.razor | 12 +- .../Pages/SpatialRelationships.razor | 12 +- .../Pages/StyledGeoJSONLayers.razor | 21 +- .../Pages/StyledGeoJSONLayers.razor.cs | 37 +- .../Pages/Swipe.razor | 14 +- .../Pages/TimeSlider.razor | 11 +- .../Pages/UpdateFeatureAttributes.razor | 11 +- .../Pages/WFSUtils.razor | 12 +- .../Pages/WebStyleSymbols.razor | 15 +- .../Shared/ProMainLayout.cs | 20 + .../Shared/ProMainLayout.razor | 94 ----- .../Shared/ProMainLayout.razor.css | 80 ---- .../Shared/ProNavMenu.razor.cs | 3 +- .../Shared/SourceNav.razor | 30 ++ .../Shared/SourceNav.razor.css | 37 ++ ...ymaptic.GeoBlazor.Pro.Sample.Shared.csproj | 1 + .../wwwroot/css/site.css | 33 -- .../wwwroot/proFunctions.js | 5 +- .../Program.cs | 2 + .../Program.cs | 2 + .../Components/App.razor | 5 +- .../Program.cs | 2 + 125 files changed, 2489 insertions(+), 1931 deletions(-) delete mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Basemaps.razor.css delete mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Drawing.razor.css delete mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Events.razor.css delete mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/FeatureLayers.razor.css delete mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Navigation.razor.css delete mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ProjectionTool.Razor.css delete mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ReactiveUtils.razor.css create mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/Accordion.razor create mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/Accordion.razor.css create mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/LayoutService.cs create mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/RadioGroup.razor create mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/RadioGroup.razor.css create mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/RadioRow.razor create mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/RadioRow.razor.css create mode 100644 samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/SamplePage.cs create mode 100644 samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Shared/ProMainLayout.cs delete mode 100644 samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Shared/ProMainLayout.razor delete mode 100644 samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Shared/ProMainLayout.razor.css create mode 100644 samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Shared/SourceNav.razor create mode 100644 samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Shared/SourceNav.razor.css delete mode 100644 samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/wwwroot/css/site.css diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Maui/MauiProgram.cs b/samples/core/dymaptic.GeoBlazor.Core.Sample.Maui/MauiProgram.cs index 8eb1c6b..e371711 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Maui/MauiProgram.cs +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Maui/MauiProgram.cs @@ -1,5 +1,6 @@ using Microsoft.Extensions.Configuration; using System.Reflection; +using dymaptic.GeoBlazor.Core.Sample.Shared.Shared; namespace dymaptic.GeoBlazor.Core.Sample.Maui; @@ -36,6 +37,7 @@ public static MauiApp CreateMauiApp() .Build(); builder.Configuration.AddConfiguration(config); builder.Services.AddGeoBlazor(builder.Configuration); + builder.Services.AddScoped(); return builder.Build(); } diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.OAuth/dymaptic.GeoBlazor.Core.Sample.OAuth/Components/RenderModeSelector.razor.css b/samples/core/dymaptic.GeoBlazor.Core.Sample.OAuth/dymaptic.GeoBlazor.Core.Sample.OAuth/Components/RenderModeSelector.razor.css index d429af1..1c80379 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.OAuth/dymaptic.GeoBlazor.Core.Sample.OAuth/Components/RenderModeSelector.razor.css +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.OAuth/dymaptic.GeoBlazor.Core.Sample.OAuth/Components/RenderModeSelector.razor.css @@ -11,4 +11,10 @@ select { padding: 0.2rem; border-radius: 0.5rem; border: 1px solid black; +} + +@media (max-width: 1074px) { + .render-mode-selector-row { + display: none; + } } \ No newline at end of file diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapProjections.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapProjections.razor index dc1425d..672affe 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapProjections.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapProjections.razor @@ -1,10 +1,9 @@ @page "/basemap-projections" +@inherits SamplePage

Basemap Projections

Basemap Projections - +

Click on the Expand Widget in the top right, select a Basemap, and the Spatial Reference is listed in the bottom left corner.

@@ -34,6 +33,11 @@ @code { private CustomOverlay? Overlay { get; set; } + public override List PageLinks => + [ + new("https://developers.arcgis.com/javascript/latest/sample-code/basemaps-portal/", "ArcGIS Maps SDK for JavaScript"), + ]; + private Task OnSpatialReferenceChanged(SpatialReference spatialReference) { _spatialReference = spatialReference; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Basemaps.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Basemaps.razor index 6799b34..608479a 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Basemaps.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Basemaps.razor @@ -1,73 +1,50 @@ @page "/basemaps" +@inherits SamplePage Basemaps

Basemaps

- +

By default, GeoBlazor will give you an OpenStreetMap basemap. With your ArcGIS API key or App Id, you can access the ArcGIS Basemap Style Service as well as hundreds of ArcGIS Online Basemaps and TileLayers.

-
-
-