From ffd4072fe6165c4021c2d83e6276a48e76ad3e04 Mon Sep 17 00:00:00 2001 From: Maggie Moeller Date: Fri, 1 May 2026 11:07:34 -0400 Subject: [PATCH 1/5] Add schema.org JSON-LD and per-sample descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sample pages legible to AI agents and screen readers without executing JavaScript. Infrastructure: - MainLayout emits a schema.org JSON-LD @graph on every page with WebSite, Organization, SoftwareApplication, WebPage, and (on sample pages) SoftwareSourceCode entities. Site-level entities mirror the GeoBlazor.com marketing site so crawlers can resolve cross-site identity. - HeadContent emits per-page meta description plus Open Graph and Twitter Card tags so sample URLs render rich previews when shared. - SamplePage gains a virtual Description property. Each sample overrides it with a detailed description: what the sample shows, what's on the screen, what the user can do, and which GeoBlazor Razor component it demonstrates. - Description is rendered visibly as a collapsible "About this sample" details element below the article and feeds the JSON-LD description on WebPage and SoftwareSourceCode. Content: - 84 Description overrides — every Core sample (54), every Pro sample (27), plus three pages migrated to SamplePage in this change (GeometryMethods, LocationMethods, GraphicsLegends). Layout: - Article padding-bottom scaled by viewport so the description clears the RenderModeSelector bar at all widths (4rem ≥1400px, 14rem 1075-1399px, 16rem <1075px). - Sidebar adds 3.5rem bottom padding so its scroll content stays above the RenderModeSelector bar. - RenderModeSelector spans full viewport width at all sizes (was offset by sidebar at wide). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Pages/BasemapProjections.razor | 12 ++ .../Pages/BasemapToggleWidgetPage.razor | 12 ++ .../Pages/Basemaps.razor | 14 ++ .../Pages/BasemapsLayerLists.razor | 13 ++ .../Pages/Bookmarks.razor | 14 ++ .../Pages/CSVLayers.razor | 13 ++ .../Pages/CalculateGeometries.razor | 14 ++ .../Pages/ClickToAdd.razor | 13 ++ .../Pages/CompassWidgetPage.razor | 13 ++ .../Pages/DisplayProjection.razor | 17 ++ .../Pages/Drawing.razor | 16 ++ .../Pages/Events.razor | 15 ++ .../Pages/FeatureLayers.razor | 14 ++ .../Pages/GeoJSONLayers.razor | 13 ++ .../Pages/GeoRSSLayers.razor | 10 + .../Pages/GeometryMethods.razor | 18 ++ .../Pages/GraphicTracking.razor | 12 ++ .../Pages/HitTests.razor | 15 ++ .../Pages/ImageryLayers.razor | 12 ++ .../Pages/ImageryTileLayers.razor | 16 ++ .../Pages/KMLLayers.razor | 13 ++ .../Pages/Labels.razor | 13 ++ .../Pages/LayerLists.razor | 14 ++ .../Pages/Legends.razor | 13 ++ .../Pages/LocateWidgetPage.razor | 13 ++ .../Pages/LocationMethods.razor | 19 ++ .../Pages/ManyGraphics.razor | 15 ++ .../Pages/MapImageLayers.razor | 15 ++ .../Pages/MarkerRotation.razor | 14 ++ .../Pages/MeasurementWidgets.razor | 16 ++ .../Pages/Navigation.razor | 15 ++ .../Pages/OpenStreetMapsLayers.razor | 11 + .../Pages/PlaceSelector.razor | 14 ++ .../Pages/PopupActions.razor | 15 ++ .../Pages/Popups.razor | 15 ++ .../Pages/ProjectionTool.razor | 17 ++ .../Pages/QueryRelatedFeatures.razor | 17 ++ .../Pages/QueryTopFeatures.razor | 17 ++ .../Pages/ReactiveUtils.razor | 14 ++ .../Pages/ReverseGeolocator.razor | 12 ++ .../Pages/ScaleBarWidgetPage.razor | 13 ++ .../Pages/Scene.razor | 15 ++ .../Pages/SearchMultipleSources.razor | 14 ++ .../Pages/ServerSideQueries.razor | 15 ++ .../Pages/ServiceAreas.razor | 13 ++ .../Pages/SqlFilterQuery.razor | 15 ++ .../Pages/SqlQuery.razor | 15 ++ .../Pages/UniqueValueRenderers.razor.cs | 15 ++ .../Pages/VectorLayer.razor | 11 + .../Pages/WCSLayers.razor | 14 ++ .../Pages/WFSLayers.razor | 14 ++ .../Pages/WMSLayers.razor | 12 ++ .../Pages/WMTSLayers.razor | 13 ++ .../Pages/WebMaps.razor | 14 ++ .../Pages/WebScenes.razor | 12 ++ .../Pages/Widgets.razor | 17 ++ .../Shared/MainLayout.razor | 189 +++++++++++++++++- .../Shared/MainLayout.razor.css | 62 +++++- .../Shared/NavMenu.razor.css | 2 +- .../Shared/RenderModeSelector.razor.css | 5 - .../Shared/SamplePage.cs | 11 +- .../Pages/ApplyEdits.razor | 12 ++ .../Pages/Binning.razor | 11 + .../Pages/ClusterPieCharts.razor | 11 + .../Pages/Clustering.razor | 12 ++ .../Pages/ClusteringPopups.razor | 12 ++ .../Pages/CustomPopupContents.razor.cs | 12 ++ .../Pages/DemographicData.razor | 12 ++ .../Pages/EditFeatureData.razor | 11 + .../Pages/GraphicsLegends.razor | 22 +- .../Pages/GroupLayers.razor | 12 ++ .../Pages/HighlightFeaturesByGeometry.razor | 12 ++ .../Pages/ImageryGroupBlend.razor | 12 ++ .../Pages/LengthAndArea.razor | 13 ++ .../Pages/OGCFeatureLayers.razor | 12 ++ .../Pages/PopupEdit.razor | 13 ++ .../Pages/PrintWidgets.razor | 11 + .../Pages/ProBookmarks.razor | 12 ++ .../Pages/ProWidgets.razor | 12 ++ .../Pages/RoutesAndDirections.razor | 12 ++ .../Pages/SearchCustomSource.razor | 12 ++ .../Pages/SketchQuery.razor | 12 ++ .../Pages/SpatialRelationships.razor | 12 ++ .../Pages/StyledGeoJSONLayers.razor.cs | 12 ++ .../Pages/Swipe.razor | 11 + .../Pages/TimeSlider.razor | 12 ++ .../Pages/UpdateFeatureAttributes.razor | 13 ++ .../Pages/WFSUtils.razor | 12 ++ .../Pages/WebStyleSymbols.razor | 13 ++ 89 files changed, 1391 insertions(+), 13 deletions(-) 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 672affe..337d835 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapProjections.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapProjections.razor @@ -38,6 +38,18 @@ new("https://developers.arcgis.com/javascript/latest/sample-code/basemaps-portal/", "ArcGIS Maps SDK for JavaScript"), ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates how basemaps in different " + + "spatial references reproject the entire view, using the BasemapGalleryWidget and PortalBasemapsSource " + + "components from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's Razor component model. " + + "The page opens with a 2D map of the world centered roughly on North America. In the upper-right corner " + + "of the map an ExpandWidget shows a basemap icon; clicking it expands a Basemap Gallery panel populated " + + "from a curated ArcGIS Online portal group containing basemaps in a variety of projections. A small " + + "CustomOverlay in the lower-left corner displays the current MapView spatial reference WKID. Selecting " + + "any basemap from the gallery triggers the OnSpatialReferenceChanged event, the view reprojects, and " + + "the WKID readout updates live. The sample is intended to demonstrate how to swap basemaps and observe " + + "the resulting spatial-reference change reactively in a Blazor application without writing JavaScript."; + private Task OnSpatialReferenceChanged(SpatialReference spatialReference) { _spatialReference = spatialReference; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapToggleWidgetPage.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapToggleWidgetPage.razor index 67c30ed..66b271d 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapToggleWidgetPage.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapToggleWidgetPage.razor @@ -42,6 +42,18 @@ new("https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-BasemapToggle.html", "Basemap Toggle API Reference") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the Basemap Toggle widget " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's BasemapToggleWidget Razor component. " + + "The page shows a 2D map of Los Angeles, California. A small toggle button appears in the lower-right " + + "corner of the map showing a thumbnail of the alternate basemap; clicking it swaps the map's primary " + + "basemap with the alternate, then back again on the next click. Above the map is a dropdown for choosing " + + "the active pair of basemap styles: Satellite paired with Colored Pencil, Topographic paired with Dark Gray, " + + "Navigation paired with Imagery, or OpenStreetMap Standard paired with Terrain. Selecting a different " + + "pair causes the map to remount with the new primary basemap and configures the toggle to swap to the " + + "matching secondary style. The sample is intended to demonstrate one-click basemap switching and " + + "configurable basemap pairs in a Blazor application without writing JavaScript."; + private int _pairIndex; private readonly (BasemapStyleName Primary, BasemapStyleName Secondary)[] _pairs = 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 608479a..1026e7c 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Basemaps.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Basemaps.razor @@ -129,6 +129,20 @@ new("https://developers.arcgis.com/javascript/latest/display-a-custom-basemap-style/", "ArcGIS Maps SDK for JavaScript"), ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the various ways to " + + "configure a Basemap on a MapView or SceneView using GeoBlazor's Basemap, BasemapStyle, PortalItem, " + + "VectorTileLayer, and TileLayer Razor components, all built on top of the ArcGIS Maps SDK for JavaScript. " + + "Above the map is a vertical group of radio rows: Default Basemap (OpenStreetMap, no API key required), " + + "2D Map Styles (a dropdown of every BasemapStyleName enum value applied to a MapView), 3D Scene Styles " + + "(the same enum applied to a SceneView), From Portal Id (a curated dropdown of ArcGIS Online basemap " + + "items such as Streets, Satellite, Hybrid, Topographic, Gray, Dark Gray, and Streets Night), and From " + + "Tile Layers (a custom basemap stitched together from a World Hillshade tile layer with a Forest and " + + "Parks vector tile layer overlaid at 75% opacity). Each row exposes its dropdown only when selected, " + + "and changing the selection refreshes the underlying MapView or SceneView with the new basemap. The " + + "sample is intended to demonstrate how to source basemaps from multiple ArcGIS providers in a Blazor " + + "application without writing JavaScript."; + private void SetBasemap(int val) { _basemapType = val; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapsLayerLists.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapsLayerLists.razor index 4028128..06335ed 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapsLayerLists.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/BasemapsLayerLists.razor @@ -64,6 +64,19 @@ new("https://www.arcgis.com/home/item.html?id=bfefe7a603c94fc29edca0f4a6662b44", "City of Bend 3D Scene") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the BasemapLayerList " + + "widget from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's BasemapLayerListWidget " + + "Razor component. The page shows a 3D scene of the City of Bend, Oregon loaded from a published " + + "WebScene PortalItem. Above the scene are two checkboxes labeled Toggle Reference Layers Visibility " + + "in Widget and Toggle Base Layers Visibility in Widget; both default to checked. The BasemapLayerList " + + "widget itself is anchored to the upper-right corner of the scene on desktop, or moved to a separate " + + "container above the scene on mobile so the map remains fully visible. The widget shows the basemap's " + + "base layers and reference layers grouped separately; expanding a group reveals each sublayer with " + + "its own visibility eye icon. Toggling either checkbox calls SetVisibleElements on the widget to hide " + + "or show the corresponding section of the list. The sample is intended to demonstrate granular control " + + "over basemap layer presentation in a Blazor application without writing JavaScript."; + protected override async Task OnAfterRenderAsync(bool firstRender) { int? oldWidth = _windowWidth; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Bookmarks.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Bookmarks.razor index dd3341f..60eda91 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Bookmarks.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Bookmarks.razor @@ -42,6 +42,20 @@ new("https://developers.arcgis.com/javascript/latest/sample-code/widgets-bookmarks/", "Bookmarks Sample") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the Bookmarks widget " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's BookmarksWidget Razor component. " + + "The page shows a 2D web map of Atlantic hurricane tracks loaded from an ArcGIS Online WebMap " + + "PortalItem. In the upper-right corner of the map an ExpandWidget is opened by default to reveal a " + + "list of named hurricane bookmarks; each bookmark has a small thumbnail and can be reordered by drag, " + + "edited via a pencil button, or extended with the Add Bookmark button. Clicking a bookmark zooms the " + + "view to the saved extent and applies a FeatureEffect to the underlying FeatureLayerView, graying out " + + "all hurricanes whose Name does not match. Below the map a heading reads Bookmarks followed by a " + + "bulleted list that mirrors the widget's Bookmarks collection; the list is wired to the reactive " + + "bookmarks.after-add event so newly added bookmarks appear immediately. The sample is intended to " + + "demonstrate reactive collection binding and feature effect filtering in a Blazor application without " + + "writing JavaScript."; + private void OnLayerViewCreate(LayerViewCreateEvent evt) { if (evt.Layer is not FeatureLayer) return; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/CSVLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/CSVLayers.razor index b28c5cb..5060a6f 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/CSVLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/CSVLayers.razor @@ -64,6 +64,19 @@ new("https://www.arcgis.com/home/item.html?id=3113eacc129942b4abde490a51aeb33f", "Stereographic Basemap") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the CSVLayer from the " + + "ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's CSVLayer Razor component. The page shows " + + "a 2D world map drawn with a Stereographic projection basemap loaded from an ArcGIS Online portal item. " + + "On top of the basemap a CSV feed of NOAA hurricane track points is rendered through a UniqueValueRenderer " + + "keyed on the Category field, with each storm category (1 through 5) drawn as a distinct PictureMarkerSymbol " + + "firefly icon. Each point exposes a PopupTemplate showing the storm name, ISO time, pressure, and wind speed. " + + "Above the map is a labeled text input plus an Add new CSV Layer! button that, once the view is rendered, " + + "constructs an additional CSVLayer from any URL the user enters and adds it to the map at runtime. An " + + "ExpandWidget in the upper-left corner houses a LegendWidget that documents the hurricane category symbols. " + + "The sample is intended to demonstrate declarative and dynamic CSV data sources in a Blazor application " + + "without writing JavaScript."; + private void OnViewRendered() { _viewRendered = true; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/CalculateGeometries.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/CalculateGeometries.razor index ca55c4e..5bd9cae 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/CalculateGeometries.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/CalculateGeometries.razor @@ -58,6 +58,20 @@ new("https://www.arcgis.com/home/item.html?id=d582a9e953c44c09bb998c7d9b66f8d4", "Charted Territory BaseMap") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates client-side geometry " + + "operations powered by the ArcGIS Maps SDK for JavaScript GeometryEngine, exposed through GeoBlazor's " + + "injectable GeometryEngine service. The page shows a 2D Charted Territory basemap zoomed in over the " + + "Santa Monica Mountains in southern California, with a purple Point, a purple Polyline, and a " + + "translucent purple Polygon already drawn as Graphics on a GraphicsLayer. A small CustomOverlay panel " + + "in the upper-right corner of the map contains four buttons: Buffer (calls GeometryEngine.GeodesicBuffer " + + "to draw a 1-kilometer buffer ring around the point), Intersect (calls GeometryEngine.Intersect to " + + "compute and draw the overlap between the polygon and the buffer using a hatched white fill), Union " + + "(calls GeometryEngine.Union to draw the merged polygon), and Reset (clears the buffer and any result " + + "graphic). Results are drawn into a separate GraphicsLayer so they can be cleared independently. The " + + "sample is intended to demonstrate calling spatial-analysis operations directly from C# in a Blazor " + + "application without writing JavaScript."; + private async Task CreateBuffer() { if (_bufferPolygon is not null) return; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ClickToAdd.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ClickToAdd.razor index 9c4de1b..97b0c01 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ClickToAdd.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ClickToAdd.razor @@ -33,6 +33,19 @@ new("https://www.arcgis.com/home/item.html?id=1e126e7520f9466c9ca28b8f28b5e500", "World Ocean Basemap"), ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates capturing map click events, " + + "drawing dynamic Graphics, and triggering custom popup actions using the OnClick event of GeoBlazor's " + + "MapView Razor component, which wraps the ArcGIS Maps SDK for JavaScript MapView and Graphic APIs. The " + + "page shows a low-zoom 2D world map drawn with the World Ocean basemap (a TileLayer loaded from an " + + "ArcGIS Online portal item). Clicking anywhere on the map runs a HitTest to detect existing graphics; " + + "if no graphic was hit, a yellow SimpleMarkerSymbol with a blue outline is added to a GraphicsLayer at " + + "the clicked location. The graphic carries a PopupTemplate that displays the longitude and latitude " + + "and exposes a custom ActionButton (Click to Add to List, decorated with the dymaptic logo); clicking " + + "the action appends the point's coordinates to a Points Clicked list rendered below the map. The sample " + + "is intended to demonstrate event-driven graphic creation and popup actions in a Blazor application " + + "without writing JavaScript."; + private async Task OnClick(ClickEvent arg) { Point point = arg.MapPoint; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/CompassWidgetPage.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/CompassWidgetPage.razor index e23544b..25ea3b3 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/CompassWidgetPage.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/CompassWidgetPage.razor @@ -37,6 +37,19 @@ new("https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Compass.html", "Compass API Reference") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the Compass widget " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's CompassWidget Razor component. " + + "The page shows an interactive 2D topographic map of the Santa Monica Mountains in southern California. " + + "Above the map is a row of buttons that rotate the view to preset bearings (45°, 90°, 180°, 270°) " + + "plus a Reset North button that returns the map to true north. A live readout displays the current " + + "rotation angle in degrees. The Compass widget itself appears in the upper-left corner of the map " + + "whenever the view is rotated away from north and disappears when aligned with north; clicking the " + + "compass icon snaps the view back to north. Map rotation is handled imperatively through " + + "MapView.SetRotation, and on-map gestures (such as right-click drag rotation or clicking the compass) " + + "synchronize the readout via the OnExtentChanged event. The sample is intended to demonstrate how to " + + "wire reactive map orientation controls in a Blazor application without writing JavaScript."; + private MapView? _mapView; private double _rotation; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/DisplayProjection.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/DisplayProjection.razor index 8eca0da..d38efb0 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/DisplayProjection.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/DisplayProjection.razor @@ -80,6 +80,23 @@ new("https://developers.arcgis.com/javascript/latest/display-projected-geometries/", "ArcGIS Maps SDK for JavaScript"), ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates how the same geometry " + + "looks under different map projections, using GeoBlazor's MapView and SpatialReference Razor components " + + "together with the ArcGIS Maps SDK for JavaScript GeoJSONLayer and a custom JavaScript hook into the " + + "GeometryEngine. The page shows a 2D world map of country polygons (from an Esri-hosted GeoJSON service) " + + "drawn over a light-blue background with a dashed rectangular extent outline. In the upper-right corner " + + "of the map a CustomOverlay holds a grouped projection dropdown organized by category (Equidistant, " + + "Conformal, Equal-area, Gnomonic, Compromise) listing options such as WGS84, World Cassini, World " + + "Equidistant Conic, World Stereographic, World Eckert VI, World Sinusoidal, North Pole Gnomonic, Web " + + "Mercator, World Gall Stereographic, World Winkel Tripel, and the Fuller / Dymaxion polyhedral map. " + + "Selecting a projection calls MapView.SetSpatialReference and the entire view reprojects on the fly. " + + "Hovering over the map invokes a custom JS extension that draws a 1000-kilometer geodesic buffer at the " + + "pointer so the user can see how distance and area distort across the chosen projection, and a popup in " + + "the lower-left corner shows the WKID and X/Y of the view center. The sample is intended to demonstrate " + + "live spatial-reference switching and JS interop in a Blazor application without writing JavaScript " + + "for the main page logic."; + private Symbol? PolySym { get; set; } private Symbol? PointSym { get; set; } private MapView? View { get; set; } diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Drawing.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Drawing.razor index 3e4f765..68606f2 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Drawing.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Drawing.razor @@ -120,6 +120,22 @@ new("https://www.arcgis.com/home/item.html?id=716b600dbbac433faa4bec9220c76b3a", "Imagery with Labels BaseMap") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates how to build and edit " + + "Point, Polyline, and Polygon geometries through GeoBlazor's Graphic, Point, Polyline, Polygon, and " + + "GraphicsLayer Razor components, all built on the ArcGIS Maps SDK for JavaScript Graphic API. Above the " + + "map are three collapsible Accordion sections (Draw a Point, Draw a Polyline, Draw a Polygon). The Point " + + "section has paired longitude and latitude number inputs and a Draw / Remove button that adds or removes " + + "a purple SimpleMarkerSymbol on the GraphicsLayer; editing either coordinate calls SetGeometry to move " + + "the point live. The Polyline section displays a table of vertex rows (longitude, latitude) plus Add Pt " + + "and Remove Pt buttons that grow or shrink the polyline; the Draw button toggles a white polyline graphic. " + + "The Polygon section works the same way for a translucent purple polygon and attaches a PopupTemplate so " + + "clicking the polygon shows a Congratulations message. Below the map (a 2D Imagery with Labels basemap " + + "centered over the Santa Monica Mountains) sits a row of Get Point Data, Get Polyline Data, and Get Polygon " + + "Data buttons that serialize the current Graphic geometry to JSON and render it underneath. The sample is " + + "intended to demonstrate two-way binding between C# state and live map geometry in a Blazor application " + + "without writing JavaScript."; + private async Task DrawPoint() { _showPoint = !_showPoint; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Events.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Events.razor index 360205f..c04ec19 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Events.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Events.razor @@ -168,6 +168,21 @@ new("https://www.arcgis.com/home/item.html?id=3d355e34cbd3405dbb3f031286f7b39b", "Daily Planet Imagery Web Map") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the full set of MapView " + + "events from the ArcGIS Maps SDK for JavaScript surfaced as Razor event callbacks on GeoBlazor's MapView " + + "component. The page shows a 2D Daily Planet imagery WebMap loaded from an ArcGIS Online portal item. " + + "Above the map are three collapsible Accordion sections grouping the live event feeds: Click/Drag/Focus " + + "Events (Click, Double Click, Hold, Drag, Blur, Focus), Pointer Events (Pointer Down, Pointer Up, Pointer " + + "Enter, Pointer Leave, Pointer Move), and Key/Mouse Events (Key Down, Key Up, Mouse Wheel, Extent). Each " + + "field in those sections shows a live JSON dump of the most recent corresponding event payload. " + + "Interactions on the map (clicks, drags, key presses, scroll-wheel zooms, etc.) flow through OnClick, " + + "OnDoubleClick, OnHold, OnDrag, OnPointerDown, OnPointerUp, OnPointerEnter, OnPointerLeave, OnPointerMove, " + + "OnKeyDown, OnKeyUp, OnMouseWheel, OnExtentChanged, OnBlur, and OnFocus callbacks; OnClick additionally " + + "calls ToScreen and ToMap to round-trip the click point. Events are throttled with EventRateLimitInMilliseconds. " + + "The sample is intended to demonstrate listening to and inspecting every map event in a Blazor application " + + "without writing JavaScript."; + private async Task OnMapClick(ClickEvent clickEvent) { _clickJson = BuildViewableJson(clickEvent); diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/FeatureLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/FeatureLayers.razor index ad79870..7d8ef75 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/FeatureLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/FeatureLayers.razor @@ -119,6 +119,20 @@ new("https://www.arcgis.com/home/item.html?id=67372ff42cd145319639a99152b15bc3", "Topographic BaseMap") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates several flavors of the " + + "FeatureLayer from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's FeatureLayer Razor " + + "component. The page shows a 2D topographic basemap zoomed in over the Santa Monica Mountains. Above " + + "the map sits a panel of toggles: a Show Trailheads Points Layer checkbox (loads the Trailheads point " + + "FeatureLayer with default symbology), a radio group with three options for the Trails polyline layer " + + "(default rendering, a custom orchid SimpleLineSymbol whose width is sized by the ELEV_GAIN field through " + + "a SizeVariable, or a dotted pink line filtered to bike-friendly trails via DefinitionExpression), a " + + "Show Trailheads Polygons checkbox (loads the Parks and Open Space polygon FeatureLayer), and a Show " + + "Client-Side Graphics Layer checkbox that creates a FeatureLayer in pure C# from inline Graphics with " + + "Calcite-icon TextSymbols, custom Field definitions, and a PopupTemplate that displays a photo via " + + "{url}. The sample is intended to demonstrate hosted, styled, filtered, and client-side feature layers " + + "side-by-side in a Blazor application without writing JavaScript."; + private bool _showPointsLayer; private int _showLinesLayer; private bool _showPolygonLayer; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeoJSONLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeoJSONLayers.razor index 7a3092d..870cdb0 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeoJSONLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeoJSONLayers.razor @@ -74,6 +74,19 @@ new("https://www.usgs.gov/programs/earthquake-hazards/earthquakes", "USGS Earthquake Hazards Program") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the GeoJSONLayer from the " + + "ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's GeoJSONLayer Razor component. The page shows " + + "a 2D dark-gray world basemap centered loosely on the Pacific. Above the map are a Show Earthquakes " + + "checkbox and a Data Source dropdown with options Past Month, Past Week, and Past Day. Toggling the " + + "checkbox loads a live USGS GeoJSON earthquake feed for the chosen period; the dropdown rewrites the " + + "feed URL and the layer reloads. Earthquakes are drawn as orange SimpleMarkerSymbol circles whose size " + + "is driven by a SizeVariable on the magnitude field (mag), so larger quakes appear as larger dots, and " + + "the layer is sorted descending by mag so big events draw on top. Clicking any earthquake opens a " + + "PopupTemplate showing magnitude, type, location, and time. A LegendWidget anchored to the bottom-right " + + "of the map documents the size ramp. The sample is intended to demonstrate consuming a remote GeoJSON " + + "feed with data-driven rendering in a Blazor application without writing JavaScript."; + private bool _showEarthquakes; private string _dataUrl = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson"; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeoRSSLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeoRSSLayers.razor index 49bcd42..bfaf1a3 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeoRSSLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeoRSSLayers.razor @@ -22,4 +22,14 @@ [ new("https://developers.arcgis.com/javascript/latest/sample-code/layers-georss/", "ArcGIS Maps SDK for JavaScript"), ]; + + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the GeoRSSLayer from the " + + "ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's GeoRSSLayer Razor component. The page shows " + + "a 2D light-gray basemap centered over the western United States at a country-level zoom. A GeoRSSLayer " + + "is added on top of the basemap, sourced from a sample GeoRSS XML feed hosted on the ArcGIS samples " + + "GitHub repository; the layer auto-renders any point, line, or polygon items it parses out of the feed " + + "using default GeoRSS symbology. There are no controls beyond the basic map navigation (pan, zoom). The " + + "sample is intended to demonstrate the simplest possible declarative consumption of a GeoRSS feed in " + + "a Blazor application without writing JavaScript."; } \ No newline at end of file diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeometryMethods.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeometryMethods.razor index f9c2de2..68fde77 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeometryMethods.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GeometryMethods.razor @@ -1,4 +1,5 @@ @page "/geometry-methods" +@inherits SamplePage @inject GeometryEngine GeometryEngine Geometry Methods

Geometry Methods

@@ -125,6 +126,23 @@ Extent extent = new Extent( @code { + public override List PageLinks => + [ + new("https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-geometryEngine.html", "GeometryEngine API Reference") + ]; + + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates GeoBlazor's GeometryEngine " + + "service which exposes geometry-manipulation operations from the ArcGIS Maps SDK for JavaScript. The page " + + "is a documentation-style reference of geometry methods grouped into four sections: Extent Methods (center " + + "an extent at a point, expand an extent by a factor, and offset an extent by X/Y distance), Point Methods " + + "(serialize a Point to ArcGIS JSON and parse JSON back to a C# Point), Polyline Methods (add a path to an " + + "existing polyline and inspect the result), and Polygon Methods (similar add-ring operations on Polygon). " + + "Each section displays a syntax-highlighted C# code snippet alongside number inputs and a button that " + + "invokes the corresponding GeometryEngine method, then renders the resulting geometry's coordinates back " + + "into a read-only text field. The sample is intended to demonstrate how to perform geometry math in pure " + + "C# from a Blazor application without writing JavaScript."; + private async Task PointToJson() { var point = new Point(-117.08, 34.1); diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GraphicTracking.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GraphicTracking.razor index ceb3e9d..df58252 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GraphicTracking.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/GraphicTracking.razor @@ -30,6 +30,18 @@ new("https://www.arcgis.com/home/item.html?id=d582a9e953c44c09bb998c7d9b66f8d4", "Charted Territory BaseMap") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates real-time graphic updates " + + "using GeoBlazor's Graphic and GraphicsLayer Razor components on top of the ArcGIS Maps SDK for JavaScript " + + "Graphic API. The page shows a 2D Charted Territory basemap centered over central India at street-level " + + "zoom, with ten point graphics randomly scattered around the center on a GraphicsLayer. Above the map " + + "are three buttons: Start / Stop (toggles a tight loop that randomly nudges each graphic's geometry on " + + "every iteration via SetGeometry, simulating live tracking, and changes its label to Stop while moving), " + + "Reset (clears the layer and regenerates the ten randomly placed points), and Center (calls MapView.GoTo " + + "to fit the view to the current Graphics collection). The Start button is disabled until the view " + + "finishes initial render via OnViewRendered. The sample is intended to demonstrate high-frequency graphic " + + "geometry updates and view framing in a Blazor application without writing JavaScript."; + protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/HitTests.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/HitTests.razor index 3b5da98..966ca91 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/HitTests.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/HitTests.razor @@ -50,6 +50,21 @@ new("https://www.arcgis.com/apps/mapviewer/index.html?url=https://sampleserver6.arcgisonline.com/arcgis/rest/services/Hurricanes/MapServer", "Hurricanes") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the MapView.HitTest API " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's MapView.HitTest method together " + + "with FeatureLayerView.Highlight. The page shows a 2D dark-gray basemap centered over the Atlantic " + + "with a FeatureLayer of historical hurricane track polylines drawn as semi-transparent thick gray " + + "lines (sourced from the Esri Hurricanes sample server). Hovering or clicking a track triggers an " + + "OnPointerMove or OnPointerDown handler that calls HitTest with a HitTestOptions filter limited to " + + "the hurricane layer's GeoBlazor id; the resulting Graphic's NAME, YEAR, CAT, and WIND_KTS attributes " + + "are read in C#. The matching storm is then highlighted in orange (configured via HighlightOptions) " + + "by querying the FeatureLayerView for ObjectIds with a where clause on YEAR and NAME and calling " + + "Highlight on the returned ids. A small CustomOverlay panel in the upper-right corner of the map " + + "displays the hovered storm's name, category, and wind speed in knots. Pointer events are throttled " + + "with EventRateLimitInMilliseconds. The sample is intended to demonstrate hit testing and feature " + + "highlighting in a Blazor application without writing JavaScript."; + private void OnLayerViewCreate(LayerViewCreateEvent createEvent) { if (_hurricaneLayer!.Id == createEvent.Layer!.Id) diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ImageryLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ImageryLayers.razor index 3c698a6..f15bc5a 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ImageryLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ImageryLayers.razor @@ -44,6 +44,18 @@ new("https://sampleserver6.arcgisonline.com/arcgis/rest/services/NLCDLandCover2001/ImageServer", "National Ground Land Cover: 2001") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the ImageryLayer from the " + + "ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's ImageryLayer Razor component, showing two " + + "different ways to add the same layer: declaratively in markup and imperatively in C# code. The page " + + "shows a 2D light-gray basemap centered over the conterminous United States. Above the map are a text " + + "input pre-populated with the URL of the NLCD 2001 Land Cover image service, an Add or Remove Imagery " + + "Layer in code button (constructs an ImageryLayer in C# from the input URL and adds it to or removes " + + "it from the MapView), and an Add new Imagery Layer in Markup button (toggles a flag that conditionally " + + "renders an ImageryLayer element directly inside the Map at 60% opacity). Both buttons are disabled " + + "until the view fires OnViewRendered. The sample is intended to demonstrate equivalent declarative " + + "and programmatic image-service layering in a Blazor application without writing JavaScript."; + private void OnViewRendered() => _mapRendered = true; public async Task AddRemoveImageryLayer() diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ImageryTileLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ImageryTileLayers.razor index 1d75b94..5326b75 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ImageryTileLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ImageryTileLayers.razor @@ -94,6 +94,22 @@ new("https://tiledimageservices.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/NLCD_2016_Land_Cover_L48_20190424/ImageServer", "Land Cover Imagery Tile Layer") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the ImageryTileLayer and " + + "dynamic UniqueValueRenderer construction from the ArcGIS Maps SDK for JavaScript exposed through " + + "GeoBlazor's ImageryTileLayer Razor component. The page shows a 2D map of the lower-48 United States " + + "rendered initially in the Albers Equal Area projection. The custom basemap is a FeatureLayer of US " + + "states drawn as dark-gray polygons with a soft drop-shadow effect, and on top of it the NLCD 2016 " + + "Land Cover ImageryTileLayer paints raster land-cover tiles. In the upper-right corner of the map a " + + "CustomOverlay panel titled Land cover types - 2016 contains a vertical Calcite radio-button group " + + "with five options (Forested Areas, Developed Areas, Cultivated Areas, Hay/Pasture Areas, Wetlands) " + + "and a Change view's projection dropdown listing Albers Equal Area, Web Mercator, and WGS 84. " + + "Selecting a land-cover type rebuilds a UniqueValueRenderer in C# (one UniqueValueInfo per NLCD_Land " + + "category in that group, colored from a per-type palette) and applies it via SetRenderer; selecting a " + + "projection calls SetSpatialReference on both the states layer and the MapView. The sample is intended " + + "to demonstrate dynamic raster restyling and live reprojection in a Blazor application without writing " + + "JavaScript."; + private async Task OnLayerViewCreated(LayerViewCreateEvent createEvent) { if (createEvent.Layer?.Id == _layer?.Id) diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/KMLLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/KMLLayers.razor index 1284f6b..8a4d1c2 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/KMLLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/KMLLayers.razor @@ -41,6 +41,19 @@ new("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/US_National_Parks_Annual_Visitation/FeatureServer/0", "USGS Earthquake Hazards Program Monitoring Center") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates loading a KML layer " + + "from the ArcGIS Maps SDK for JavaScript via GeoBlazor's KMLLayer Razor component. " + + "The page shows a 2D world map rendered with the dark gray basemap style. " + + "Above the map is an editable text input pre-filled with a USGS earthquake feed URL " + + "(KML data for major earthquakes of magnitude 5.8 or greater over the last 30 days), " + + "alongside two buttons: 'Add or Remove KML Layer in code' which imperatively toggles a " + + "KMLLayer instance on the MapView via AddLayer/RemoveLayer, and 'Add new KML Layer in Markup' " + + "which toggles a declarative KMLLayer element rendered inside the Map markup. " + + "When a layer is loaded, earthquake locations are plotted as KML placemarks on top of the basemap. " + + "The sample is intended to demonstrate two equivalent ways to consume KML data in a Blazor " + + "application without writing JavaScript."; + private void OnViewRendered() => _mapRendered = true; // ReSharper disable once InconsistentNaming diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Labels.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Labels.razor index a376dfc..90ec035 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Labels.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Labels.razor @@ -38,4 +38,17 @@ new("https://developers.arcgis.com/javascript/latest/sample-code/labels-basic/", "ArcGIS Maps SDK for JavaScript"), new("https://www.arcgis.com/home/item.html?id=372b7caa8fe340b0a6300df93ef18a7e", "Labels BaseMap") ]; + + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates feature labeling " + + "from the ArcGIS Maps SDK for JavaScript using GeoBlazor's Label and TextSymbol Razor components. " + + "The page shows a 2D web map centered on the Joshua Tree area of southern California, " + + "loaded from an ArcGIS Online portal item. Overlaid on top is a FeatureLayer of trail markers, " + + "rendered as small dark green circles. Each marker is automatically labeled above its center " + + "with the value of the MARKER_ACTIVITY field, drawn in bold green Playfair Display font on a " + + "translucent lavender background with a green border. The label text, placement, font, and " + + "background styling are all configured declaratively through the Label, TextSymbol, MapFont, " + + "and LabelExpressionInfo components. There are no interactive controls — the user simply pans " + + "and zooms the map. The sample is intended to demonstrate how to attach data-driven labels to " + + "feature layers in a Blazor application without writing JavaScript."; } \ No newline at end of file diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/LayerLists.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/LayerLists.razor index a757ab9..de62a6e 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/LayerLists.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/LayerLists.razor @@ -48,6 +48,20 @@ new("https://www.arcgis.com/home/item.html?id=adfad6ee6c6043238ea64e121bb6429a", "San Francisco - Urban Planning Web Scene") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the LayerList widget " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's LayerListWidget Razor component. " + + "The page shows a 3D San Francisco urban planning web scene loaded from an ArcGIS Online portal item, " + + "containing multiple layers including transit, buildings, and zoning. " + + "On wide screens, the LayerList widget is anchored in the upper-right corner of the SceneView; on " + + "narrow mobile layouts it is rendered in a separate container above the scene so the map remains fully visible. " + + "Inside the widget, each layer has a right-arrow toggle to reveal sublayers, an eye icon to toggle " + + "visibility on the basemap, and a legend icon to expand the layer's symbology. " + + "An OnListItemCreated handler customizes each list item by enabling visibility, attaching a legend panel, " + + "and prefixing 'Mass ' to any layer titled 'Transit'. " + + "The sample is intended to demonstrate building an interactive layer manager in a Blazor application " + + "without writing JavaScript."; + protected override async Task OnAfterRenderAsync(bool firstRender) { int? oldWidth = _windowWidth; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Legends.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Legends.razor index bff31c6..ff79d98 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Legends.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Legends.razor @@ -109,6 +109,19 @@ new("https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Legend.html", "Legend API Reference") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the Legend widget " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's LegendWidget Razor component. " + + "The page shows a 2D topographic map of the Santa Monica Mountains in southern California. " + + "Above the map is a column of three checkboxes labeled 'Show Census Layer', 'Show Trails Layer', " + + "and 'Show Parks Layer'. Toggling each checkbox adds or removes a corresponding FeatureLayer: " + + "census block points sized by population using a SizeVariable, trails colored green for bike-allowed " + + "and red dashed for no-bikes via a UniqueValueRenderer, and parks rendered as semi-transparent green " + + "polygons via a SimpleRenderer. The LegendWidget itself is anchored in the lower-right corner of the " + + "map and automatically updates to describe each layer's symbols and renderer categories as layers are " + + "added or removed. The sample is intended to demonstrate how a Legend automatically reflects layer " + + "symbology in a Blazor application without writing JavaScript."; + private bool _showCensusLayer; private bool _showTrailsLayer; private bool _showParksLayer; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/LocateWidgetPage.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/LocateWidgetPage.razor index fbd45a5..58a06fe 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/LocateWidgetPage.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/LocateWidgetPage.razor @@ -48,5 +48,18 @@ new("https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Locate.html", "Locate API Reference") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the Locate widget from " + + "the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's LocateWidget Razor component. The page " + + "shows a 2D navigation basemap of the contiguous United States. A round Locate button (a circle with " + + "crosshairs) sits in the upper-left corner of the map. Clicking it triggers the browser's Geolocation API " + + "and animates the map to the user's current position; most browsers will prompt with an Allow permissions " + + "dialog the first time the button is clicked. Above the map is a Scale dropdown with four preset values — " + + "1,500 (street level), 5,000 (neighborhood), 25,000 (city), and 100,000 (region) — that controls how far " + + "the view zooms in when locating. Changing the scale updates the LocateWidget's Scale parameter " + + "reactively without remounting the map, so subsequent clicks of the Locate button fly in at the new zoom. " + + "The sample is intended to demonstrate browser geolocation integration and reactive widget parameter " + + "binding in a Blazor application without writing JavaScript."; + private int _scale = 1500; } diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/LocationMethods.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/LocationMethods.razor index 0371638..06d777f 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/LocationMethods.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/LocationMethods.razor @@ -1,4 +1,5 @@ @page "/locator-methods" +@inherits SamplePage @inject LocationService LocationService Locator Methods

Locator Methods

@@ -73,6 +74,24 @@ List results = await Location.SuggestLocations( @code { + public override List PageLinks => + [ + new("https://developers.arcgis.com/javascript/latest/api-reference/esri-rest-locator.html", "Locator API Reference") + ]; + + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates GeoBlazor's LocationService " + + "which wraps the ArcGIS Maps SDK for JavaScript Locator REST module for geocoding and reverse geocoding. " + + "The page is a documentation-style reference of four LocationService methods, each presented with a " + + "syntax-highlighted C# code snippet, an action button, and a result panel: Addresses To Locations (batch " + + "forward-geocode a list of Address records to coordinates with confidence scores), Address To Locations " + + "(forward-geocode a single Address with extended OutFields), Location To Address (reverse-geocode a Point " + + "to a street address), and Suggest Locations (return autocomplete suggestions for partial input near a " + + "given Point). Clicking each button invokes the corresponding LocationService call against the ArcGIS " + + "World GeocodeServer and renders the returned AddressCandidate or SuggestionResult collection beneath the " + + "button. The sample is intended to demonstrate how to perform geocoding entirely in C# from a Blazor " + + "application without writing JavaScript."; + List _suggestions = []; AddressCandidate? _address; List _locations1 = []; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ManyGraphics.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ManyGraphics.razor index 53f0a6b..33a9804 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ManyGraphics.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ManyGraphics.razor @@ -52,6 +52,21 @@ new("https://developers.arcgis.com/javascript/latest/api-reference/esri-Graphic.html", "ArcGIS Maps SDK for JavaScript") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates bulk-rendering " + + "large numbers of Graphic objects from the ArcGIS Maps SDK for JavaScript via GeoBlazor's " + + "MapView, GraphicsLayer, and Graphic Razor components. " + + "The page shows a 2D map of Brazil and surrounding South America rendered with an OpenStreetMap basemap. " + + "Above the map is a form with a geometry-type dropdown (Point, Polyline, Polygon), numeric inputs for " + + "the number of graphics to generate (default 10,000) and the serialization chunk size (default 200, or " + + "100 in MAUI), and three buttons: 'Add Graphics To View' which calls MapView.AddGraphics in chunks, " + + "'Add Graphics To Layer' which calls GraphicsLayer.Add in chunks, and 'Clear Graphics' which removes " + + "everything. While generating, the controls disable to prevent overlapping requests. " + + "Each generated graphic carries a SimpleMarkerSymbol, SimpleLineSymbol, or SimpleFillSymbol along with " + + "a PopupTemplate so users can click any graphic to see its attributes. " + + "The sample is intended to demonstrate efficient batch graphic rendering in a Blazor application " + + "without writing JavaScript."; + protected override void OnInitialized() { base.OnInitialized(); diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/MapImageLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/MapImageLayers.razor index f9869a1..5f76dd5 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/MapImageLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/MapImageLayers.razor @@ -281,6 +281,21 @@ new("https://www.arcgis.com/home/item.html?id=d7892b3c13b44391992ecd42bfa92d01", "City Pool Permits Map") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the MapImageLayer " + + "from the ArcGIS Maps SDK for JavaScript via GeoBlazor's MapImageLayer and Sublayer Razor components. " + + "Unlike feature layers, MapImageLayer requests dynamically rendered images from the server rather " + + "than vector features. The page shows a 3D scene with a dark gray basemap. " + + "Above the scene is a radio group with five options: a static City Pool Permits map, a USA-services " + + "layer with toggleable Highways/Cities/Railroads/States sublayers (with click-to-toggle chips below the map), " + + "a population-filtered cities sublayer driven by a SliderWidget that updates the layer's " + + "DefinitionExpression as the user drags, sublayers with custom SimpleRenderers for state/highway/city " + + "symbols, and sublayers with custom Labels including state-name and city-name text symbols at " + + "different scale ranges. As the user changes the radio selection the corresponding MapImageLayer " + + "configuration is rendered, and the view zooms to the layer's extent or to a Chicago-area view for " + + "the labels demo. The sample is intended to demonstrate MapImageLayer sublayer toggling, custom " + + "rendering, and dynamic filtering in a Blazor application without writing JavaScript."; + private async Task OnLayerViewCreate(LayerViewCreateEvent createEvent) { if (createEvent.Layer is MapImageLayer imageLayer) diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/MarkerRotation.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/MarkerRotation.razor index 1c2d68b..be8c753 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/MarkerRotation.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/MarkerRotation.razor @@ -33,4 +33,18 @@ [ new("https://developers.arcgis.com/javascript/latest/display-a-web-map/", "ArcGIS Maps SDK for JavaScript"), ]; + + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates data-driven marker " + + "rotation and sizing from the ArcGIS Maps SDK for JavaScript via GeoBlazor's PictureMarkerSymbol, " + + "RotationVariable, and SizeVariable Razor components. " + + "The page shows a 2D map zoomed to South America rendered with the ArcGIS imagery basemap. " + + "A FeatureLayer of weather stations is overlaid on top, where each station is symbolized by a small " + + "blue arrow icon loaded from a Wikimedia SVG via PictureMarkerSymbol. " + + "There are no on-screen controls — the visualization itself does the work: each arrow's rotation angle " + + "is bound to the WIND_DIRECT field using geographic rotation, so arrows point in the direction the " + + "wind is blowing, while each arrow's size is scaled between 8 and 40 pixels based on the WIND_SPEED " + + "field via a SizeVariable. The user pans and zooms to explore the wind field. " + + "The sample is intended to demonstrate data-driven symbol rotation and sizing in a Blazor application " + + "without writing JavaScript."; } \ No newline at end of file diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/MeasurementWidgets.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/MeasurementWidgets.razor index 2611fe1..0f46f30 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/MeasurementWidgets.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/MeasurementWidgets.razor @@ -66,6 +66,22 @@ new("https://www.arcgis.com/home/item.html?id=990d0191f2574db495c4304a01c3e65b", "NFL Stadiums in the USA") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates 2D measurement tools " + + "from the ArcGIS Maps SDK for JavaScript via GeoBlazor's DistanceMeasurement2DWidget and " + + "AreaMeasurement2DWidget Razor components. " + + "The page shows a 2D web map of NFL stadium locations across the United States loaded from an " + + "ArcGIS Online portal item. In the top-right corner of the map, a custom overlay labeled 'Measure Tools' " + + "displays two icon buttons: a measure-area button and a measure-line button, which highlight when active. " + + "Clicking the line button starts the DistanceMeasurement2D widget so the user clicks on the map to " + + "drop points and double-clicks to finish, displaying the horizontal distance between points; clicking " + + "the area button starts the AreaMeasurement2D widget for polygon area measurement. " + + "A 'Show Details' button in the bottom-left corner toggles between a compact mode (where the widget UI " + + "is hidden in an off-map container) and a full panel anchored to the bottom-right of the map that " + + "exposes options to change measurement units. " + + "The sample is intended to demonstrate interactive measurement tooling in a Blazor application " + + "without writing JavaScript."; + private async Task OnDistanceButtonClicked() { await SetActiveWidget("distance"); diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Navigation.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Navigation.razor index 260f550..8c94acc 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Navigation.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Navigation.razor @@ -56,6 +56,21 @@ new("https://www.arcgis.com/home/item.html?id=826498a48bd0424f9c9315214f2165d4", "Colored Pencil BaseMap") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates programmatic map " + + "navigation using GeoBlazor's MapView Razor component bound to .NET properties from the ArcGIS " + + "Maps SDK for JavaScript. " + + "The page shows a 2D map rendered with the 'Colored Pencil' basemap loaded from an ArcGIS Online " + + "portal item, initially centered near Thousand Oaks, California at zoom level 11. " + + "Above the map is a form with four numeric inputs for Latitude, Longitude, Zoom, and Rotation " + + "(degrees); changing any value re-binds the MapView's corresponding parameter and the map updates " + + "in real time. Note that once the user manually drags or zooms the map, those one-way bindings stop " + + "applying so the map does not snap back. " + + "Below the map is a 'Get Extent' button which calls MapView.GetExtent and renders the resulting " + + "Extent object as formatted JSON beneath the button. " + + "The sample is intended to demonstrate two-way reactive map navigation and extent retrieval in a " + + "Blazor application without writing JavaScript."; + private void OnViewRendered() { Console.WriteLine("View Rendered"); diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/OpenStreetMapsLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/OpenStreetMapsLayers.razor index ba4bb4b..639c20d 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/OpenStreetMapsLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/OpenStreetMapsLayers.razor @@ -18,4 +18,15 @@ [ new("https://developers.arcgis.com/javascript/latest/api-reference/esri-layers-OpenStreetMapLayer.html", "ArcGIS Maps SDK for JavaScript"), ]; + + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the OpenStreetMap layer " + + "from the ArcGIS Maps SDK for JavaScript via GeoBlazor's OpenStreetMapLayer Razor component. " + + "The page shows a 3D SceneView of the entire globe at zoom level 1, with world-elevation terrain " + + "applied to the ground. The OpenStreetMapLayer is added directly inside the Map (no portal item or " + + "API key required, because PromptForArcGISKey is set to false), so the user sees crowdsourced " + + "OpenStreetMap tiles draped over the elevation surface. There are no on-screen controls — the user " + + "simply pans, rotates, tilts, and zooms the globe to explore. " + + "The sample is intended to demonstrate using a free OpenStreetMap basemap source on a 3D scene in a " + + "Blazor application without writing JavaScript."; } \ No newline at end of file diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/PlaceSelector.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/PlaceSelector.razor index 58fd21a..4e7a2e4 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/PlaceSelector.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/PlaceSelector.razor @@ -38,6 +38,20 @@ new("https://www.arcgis.com/home/item.html?id=00f90f3f3c9141e4bea329679b257142", "Streets (with Relief) BaseMap") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates place-category geocoding " + + "from the ArcGIS Maps SDK for JavaScript via GeoBlazor's MapView.FindPlaces method together with " + + "AddressQuery, SimpleMarkerSymbol, and PopupTemplate Razor components. " + + "The page shows a 2D map rendered with a streets-with-relief basemap, centered on Tromsø in northern " + + "Norway at zoom level 13. " + + "In the top-right corner of the map a dropdown lists place-type categories: Parks and Outdoors, " + + "Coffee shop, Gas station, Food, and Hotel. When the user selects a category, the page builds an " + + "AddressQuery against the ArcGIS World Geocoder service and calls FindPlaces, which renders matching " + + "locations as small black-with-white-outline markers across the visible area (up to 25 results). " + + "Clicking a marker opens a popup showing the place name and address pulled from the geocoder. " + + "The sample is intended to demonstrate category-based place search and result rendering in a Blazor " + + "application without writing JavaScript."; + public MapView? View { get; set; } public SimpleMarkerSymbol? Symbol { get; set; } public PopupTemplate? Popup { get; set; } diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/PopupActions.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/PopupActions.razor index 4e27bce..066a71a 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/PopupActions.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/PopupActions.razor @@ -37,6 +37,21 @@ new("https://www.arcgis.com/apps/mapviewer/index.html?url=https://services.arcgis.com/V6ZHFr6zdgNZuVG0/ArcGIS/rest/services/TrailRuns/FeatureServer&source=sd", "Trail Runs Feature Service") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates custom popup actions " + + "from the ArcGIS Maps SDK for JavaScript via GeoBlazor's PopupTemplate, ActionButton, and " + + "PopupWidget Razor components. " + + "The page shows a 2D map of the Inland Empire area near San Bernardino, California, rendered with the " + + "Modern Antique basemap loaded from an ArcGIS Online portal item, at zoom level 11. " + + "A FeatureLayer of trail-run lines is overlaid on top. There are no controls outside the map — the " + + "user clicks on any trail to open a popup titled 'Trail Run' that shows the trail name. The popup " + + "includes a custom action button labeled 'Measure Length', identified by a small ruler icon. Clicking " + + "the action invokes the .NET MeasureThis callback, which retrieves the selected feature's geometry, " + + "calls the injected GeometryEngine.GeodesicLength to compute the length in miles, and updates the " + + "popup content to display the rounded distance. " + + "The sample is intended to demonstrate adding custom buttons and .NET callbacks inside ArcGIS popups " + + "in a Blazor application without writing JavaScript."; + private MapView? MapView { get; set; } private async Task MeasureThis() diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Popups.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Popups.razor index fbb6fb0..d2b2d43 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Popups.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Popups.razor @@ -82,6 +82,21 @@ new("https://www.arcgis.com/home/item.html?id=f35ef07c9ed24020aadd65c8a65d3754", "Modern Antique BaseMap") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates three styles of feature " + + "popups from the ArcGIS Maps SDK for JavaScript via GeoBlazor's PopupTemplate, MediaPopupContent, " + + "ColumnChartMediaInfo, and FieldsPopupContent Razor components. " + + "The page shows a 2D map of the Santa Monica Mountains rendered with the Modern Antique basemap. " + + "Above the map is a radio group with three options: 'Display Attributes Popup' (renders a Trailheads " + + "FeatureLayer with a popup showing trail name, city, cross street, parking, and elevation as " + + "formatted HTML), 'Display Elevation Chart Popup' (renders a Trails FeatureLayer with a popup that " + + "embeds a column chart visualizing min and max elevation), and 'Display Table Popup' (renders a " + + "Parks and Open Space FeatureLayer with a popup that lists agency, type, access, and acreage as a " + + "table of editable FieldInfo entries). Selecting a radio option swaps the active FeatureLayer and " + + "closes any open popup; clicking a feature on the map then opens the corresponding popup style. " + + "The sample is intended to demonstrate text, chart, and tabular popup formats in a Blazor application " + + "without writing JavaScript."; + private MapView? MapView { get; set; } private int _showPopupOption; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ProjectionTool.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ProjectionTool.razor index b17229a..057b5b5 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ProjectionTool.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ProjectionTool.razor @@ -185,6 +185,23 @@ new("https://developers.arcgis.com/javascript/latest/api-reference/esri-geometry-projection.html", "ArcGIS Maps SDK for JavaScript"), ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the ProjectionEngine " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's injected ProjectionEngine " + + "service together with SpatialReference and GeographicTransformation Razor components. " + + "The page shows two side-by-side 2D maps, each backed by a GeoJSONLayer of generalized world country " + + "polygons rendered as white shapes with purple outlines on a light blue background. " + + "Above the maps is a Starting Point form with longitude and latitude inputs (defaulting to a point in " + + "northeast Greenland). Each map has its own dropdown of Wkid options grouped by projection family — " + + "Equidistant (4326, 54028, 54027), Conformal (54026), Equal-area (54010, 54008), Gnomonic (102034), " + + "and Compromise (3857, 54016, 54042, 54050) — and a live readout of the projected X/Y coordinates of " + + "the starting point. A purple SimpleMarkerSymbol marks the starting point in each view. " + + "Below the maps is a 'Get Transformation' panel that calls ProjectionEngine.Project and " + + "ProjectionEngine.GetTransformation to display the starting Wkid, each GeographicTransformationStep, " + + "and the ending Wkid. " + + "The sample is intended to demonstrate spatial reference projection and transformation computation " + + "in a Blazor application without writing JavaScript."; + private MapView? _view1; private MapView? _view2; private Graphic? _graphic1; diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/QueryRelatedFeatures.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/QueryRelatedFeatures.razor index 160d1a7..ad8d31b 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/QueryRelatedFeatures.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/QueryRelatedFeatures.razor @@ -78,6 +78,23 @@ new("https://www.arcgis.com/home/item.html?id=https://www.arcgis.com/home/item.html?id=7a301e848a7c4bfcaefdac4fe98a7f99", "Aggregation of Major US Cities") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the queryRelatedFeatures " + + "method from the ArcGIS Maps SDK for JavaScript via GeoBlazor's FeatureLayer.QueryRelatedFeatures, " + + "RelationshipQuery, and FeatureLayerView.Highlight APIs. " + + "The page shows a 2D map of the contiguous United States at zoom level 3, rendered from an ArcGIS " + + "Online basemap. A FeatureLayer of hexagonal aggregation cells, each representing a region containing " + + "major US cities, is overlaid on top. " + + "An ExpandWidget anchored in the top-right corner of the map can be opened to reveal a LegendWidget. " + + "A custom overlay in the bottom-left corner contains a 'US Cities' panel with instructions and an " + + "initially empty results table. When the user clicks any hexagon on the map, the page first queries " + + "the layer for the matching ObjectIds, highlights the clicked hexagon via the FeatureLayerView, then " + + "issues a RelationshipQuery to retrieve the related city records (NAME and SUM_POPULATION) and " + + "renders them as rows in the table. A 'Clear Query' button below the table removes the highlight and " + + "empties the results. " + + "The sample is intended to demonstrate spatial click-to-query plus related-record retrieval in a " + + "Blazor application without writing JavaScript."; + private async Task OnClick(ClickEvent clickEvent) { await ClearMap(); diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/QueryTopFeatures.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/QueryTopFeatures.razor index 58eff62..113cc50 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/QueryTopFeatures.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/QueryTopFeatures.razor @@ -154,6 +154,23 @@ new("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/US_National_Parks_Annual_Visitation/FeatureServer/0", "US National Parks Annual Visitation") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the QueryTopFeatures " + + "method from the ArcGIS Maps SDK for JavaScript via GeoBlazor's FeatureLayer.QueryTopFeatures, " + + "TopFeaturesQuery, and TopFilter APIs. " + + "The page shows a 2D map of the contiguous United States at zoom level 3, with a FeatureLayer of " + + "national parks rendered as small tree-emoji PictureMarkerSymbols. " + + "A Calcite panel anchored to the right side of the map presents the controls: a horizontal radio group " + + "to choose 'Most visited' (descending) or 'Least visited' (ascending), a select for how many parks " + + "to return per state (1, 2, or 3), and a select for the time range (Total of all time, 2018, 2019, " + + "or 2020). Two buttons — 'Query parks' (solid when active) and 'Clear query' — run the query or reset. " + + "Running the query calls QueryTopFeatures using a TopFilter grouped by State, ordered by the chosen " + + "field/direction, and applies a FeatureFilter on the FeatureLayerView so only the top matching parks " + + "remain visible. Results render as a Calcite list below the form, each item labeled with the park " + + "name plus visitor count and state; clicking a result opens that park's popup on the map. " + + "The sample is intended to demonstrate group-wise top-N feature queries in a Blazor application " + + "without writing JavaScript."; + private void OnLayerViewCreate(LayerViewCreateEvent evt) { if (evt.Layer!.Id == _featureLayer?.Id) diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ReactiveUtils.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ReactiveUtils.razor index 6d44b84..64ef262 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ReactiveUtils.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ReactiveUtils.razor @@ -218,6 +218,20 @@ else new("https://www.arcgis.com/home/item.html?id=0614ea1f9dd043e9ba157b9c20d3c538", "Paris 3D Web Scene") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the reactiveUtils module " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's AddReactiveWatcher, " + + "AddReactiveListener, and AddReactiveWaiter methods on SceneView and widget components. " + + "The page loads a 3D web scene of Paris into a SceneView with a HomeWidget in the upper-left and a " + + "LayerListWidget in the upper-right. Above the scene are three collapsible Accordion sections. " + + "The Add Watchers section provides checkboxes to subscribe to popup-open state, the view's center " + + "point, the view's extent, the visible-layer list, and a one-time zoom watcher; each prints its " + + "current value live as the user pans, zooms, or toggles layers. The Add Listeners section attaches " + + "click and drag event listeners that serialize and display each event payload as JSON. The Add " + + "Waiters section uses a waiter to detect when the HomeWidget becomes visible and a second checkbox " + + "to toggle that visibility. The sample is intended to demonstrate how to bind C# callbacks to " + + "reactive ArcGIS view and widget properties in a Blazor application without writing JavaScript."; + private async Task OnViewRendered() { await _homeWidget!.SetVisibility(false); diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ReverseGeolocator.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ReverseGeolocator.razor index 7fbab3e..414755f 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ReverseGeolocator.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ReverseGeolocator.razor @@ -38,6 +38,18 @@ new("https://www.arcgis.com/home/item.html?id=8dda0e7b5e2d4fafa80132d59122268c", "Streets (WGS84) BaseMap") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates reverse geocoding " + + "(LocationToAddress) from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's " + + "LocationService and PopupTemplate Razor components. The page shows a 2D streets basemap centered " + + "near Quito, Ecuador. Above the map sits an instructional paragraph; once the user clicks anywhere " + + "on the map the page also displays the selected latitude and longitude and the resolved street " + + "address in a Selected Point heading. The click handler converts the click point into an address " + + "by calling LocationService.LocationToAddress against the ArcGIS World GeocodeServer, then opens a " + + "PopupTemplate at the clicked location whose title is the longitude and latitude and whose content " + + "is the returned address. The sample is intended to demonstrate how to perform reverse geocoding " + + "and bind the result to an interactive popup in a Blazor application without writing JavaScript."; + public MapView? View { get; set; } public PopupTemplate? Popup { get; set; } diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ScaleBarWidgetPage.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ScaleBarWidgetPage.razor index a63c5b5..e8fd465 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ScaleBarWidgetPage.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ScaleBarWidgetPage.razor @@ -46,6 +46,19 @@ new("https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-ScaleBar.html", "ScaleBar API Reference") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the Scale Bar widget from " + + "the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's ScaleBarWidget Razor component. The page " + + "shows a 2D topographic basemap of the contiguous United States with a scale bar overlay in the lower-left " + + "corner of the map. The scale bar reports the real-world distance corresponding to a fixed pixel length " + + "on the map, updating live as the user zooms in or out. Above the map are two dropdowns: a Unit selector " + + "that switches between Imperial (miles and feet), Metric (kilometers and meters), and Dual (both unit " + + "systems shown simultaneously); and a Style selector that switches the bar's appearance between Ruler " + + "(a graduated tick-marked bar) and Line (a simple line with end markers). Both Unit and Style are bound " + + "reactively to the widget's parameters, so changes update the bar in place without remounting the map. " + + "The sample is intended to demonstrate map-scale visualization and reactive widget configuration in a " + + "Blazor application without writing JavaScript."; + private ScaleUnit _unit = ScaleUnit.Imperial; private ScaleBarWidgetStyle _style = ScaleBarWidgetStyle.Ruler; } diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Scene.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Scene.razor index 148c83c..e29e829 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Scene.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Scene.razor @@ -68,6 +68,21 @@ new("https://developers.arcgis.com/javascript/latest/api-reference/esri-Graphic.html#attributes", "Graphic Attributes Reference") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates a 3D SceneView, " + + "GraphicsLayer, and Graphic attributes binding from the ArcGIS Maps SDK for JavaScript exposed " + + "through GeoBlazor's SceneView, Graphic, and PopupTemplate Razor components. The page shows an " + + "imagery basemap with world elevation centered over the Santa Monica Mountains tilted at 76 " + + "degrees, with a purple polygon graphic declared in Razor markup and a smaller green point graphic " + + "added imperatively from C# after the view renders. Above the scene is a form group with text, " + + "date, time, number, and checkbox inputs that edit the polygon's Name, Description, Date, Number, " + + "and Boolean attributes; the inputs are disabled until the scene finishes rendering. A second " + + "panel below shows the C# record type used as the popup's Object attribute. Clicking either " + + "graphic opens a popup whose title and body are bound to the live attribute values, and changing " + + "any input updates both graphics' attributes through AttributesDictionary.AddOrUpdate. The sample " + + "is intended to demonstrate two-way binding between Blazor inputs and ArcGIS Graphic attributes " + + "in a 3D scene without writing JavaScript."; + private async Task OnViewRendered() { if (!_rendered) diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SearchMultipleSources.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SearchMultipleSources.razor index c0c5c84..e544509 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SearchMultipleSources.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SearchMultipleSources.razor @@ -60,4 +60,18 @@ new("https://developers.arcgis.com/javascript/latest/sample-code/widgets-search-multiplesource/", "ArcGIS Maps SDK for JavaScript"), new("https://www.arcgis.com/home/item.html?id=1970c1995b8f44749f4b9b6e81b5ba45", "Dark Gray BaseMap") ]; + + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the Search widget " + + "configured with multiple custom sources from the ArcGIS Maps SDK for JavaScript exposed through " + + "GeoBlazor's SearchWidget, LayerSearchSource, and LocatorSearchSource Razor components. The page " + + "shows a 2D dark-gray basemap of the contiguous United States. In the upper-right corner of the " + + "map sits a Search widget whose source dropdown lets the user choose between Congressional " + + "Districts (a FeatureLayer keyed by DISTRICTID), Senators (a FeatureLayer keyed by Name or Party " + + "with a custom suggestion template and a senate icon picture marker symbol), the ArcGIS World " + + "Geocoding Service, or all three at once with the placeholder Senator or World Location Service. " + + "Selecting a result zooms the map and opens a PopupTemplate appropriate to that source. The " + + "default sources are disabled so only the configured ones appear. The sample is intended to " + + "demonstrate combining feature-layer search and a world geocoder behind a single search widget " + + "in a Blazor application without writing JavaScript."; } \ No newline at end of file diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ServerSideQueries.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ServerSideQueries.razor index 76a527b..95f9fc4 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ServerSideQueries.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ServerSideQueries.razor @@ -54,6 +54,21 @@ new("https://www.arcgis.com/home/item.html?id=234d2e3f6f554e0e84757662469c26d3", "SF Crimes by Block Group") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates server-side " + + "FeatureLayer queries (queryFeatures) from the ArcGIS Maps SDK for JavaScript exposed through " + + "GeoBlazor's FeatureLayer.CreateQuery, QueryFeatures, and PopupWidget Razor components. The page " + + "shows a 2D dark-gray basemap of San Francisco overlaid with a crimes-by-block-group FeatureLayer. " + + "A LegendWidget for the crime layer sits in the lower-left corner of the map. In the upper-right " + + "a CustomOverlay panel contains a dropdown labeled Basic Query or Query By Distance. The user " + + "picks a query type and clicks anywhere on the map; the click point is sent as the query geometry " + + "(with a half-mile distance buffer when Query By Distance is selected) and the matching features " + + "are returned from the server. A blue marker is drawn at the click point, an optional buffer " + + "polygon is drawn for distance queries, and the docked PopupWidget at the bottom-right is " + + "populated with the returned features so the user can page through them. The sample is intended " + + "to demonstrate executing spatial queries against a hosted FeatureLayer in a Blazor application " + + "without writing JavaScript."; + [Inject] public required IJSRuntime JsRuntime { get; set; } diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ServiceAreas.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ServiceAreas.razor index 009f4dc..9079fe9 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ServiceAreas.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ServiceAreas.razor @@ -24,6 +24,19 @@ new("https://developers.arcgis.com/javascript/latest/find-service-areas/", "ArcGIS Maps SDK for JavaScript"), ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates service-area " + + "(drive-time) network analysis from the ArcGIS Maps SDK for JavaScript exposed through " + + "GeoBlazor's MapView.SolveServiceArea method. The page shows a 2D navigation basemap centered on " + + "Osaka, Japan at zoom level 11. Above the map is an instructional paragraph telling the user to " + + "click on any point on the map to see a set of Service Areas representing 5, 10, and 15 minute " + + "drivable distance bands. When the user clicks, a small white marker is placed at the clicked " + + "point and the page calls SolveServiceArea against the ArcGIS World ServiceAreas REST endpoint " + + "with break values of 5, 10, and 15 minutes; the resulting drive-time polygons are added to the " + + "map and styled with a translucent purple fill, with previous graphics cleared on each click. " + + "The sample is intended to demonstrate solving and visualizing network service areas from a " + + "hosted routing service in a Blazor application without writing JavaScript."; + private async Task OnClick(ClickEvent clickEvent) { await _areaGraphic.SetGeometry(clickEvent.MapPoint); diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SqlFilterQuery.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SqlFilterQuery.razor index 5b9cf22..f79aec2 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SqlFilterQuery.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SqlFilterQuery.razor @@ -48,6 +48,21 @@ new("https://www.arcgis.com/home/item.html?id=7e2b9be8a9c94e45b7f87857d8d168d6", "Streets (Night) BaseMap") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates client-side filtering " + + "of a FeatureLayer through its DefinitionExpression from the ArcGIS Maps SDK for JavaScript " + + "exposed through GeoBlazor's FeatureLayer Razor component. The page shows a 2D night-themed " + + "streets basemap of the Santa Monica Mountains in Los Angeles County overlaid with a parcels " + + "FeatureLayer. In the upper-right corner of the map a CustomOverlay hosts a styled dropdown " + + "select. The dropdown's first option is the placeholder Choose a SQL where clause which maps to " + + "a no-results expression (1=0); the remaining options are five SQL where-clause snippets such as " + + "Roll_LandValue < 200000, TaxRateArea = 10853, Bedrooms5 > 0, UseType = 'Residential', and " + + "Roll_RealEstateExemp > 0. Selecting a clause binds it to the FeatureLayer's DefinitionExpression " + + "so only matching parcels are drawn on the map, and clicking any visible parcel opens a popup " + + "with its UseType, description, and land value. The sample is intended to demonstrate filtering " + + "a hosted FeatureLayer with a server-evaluated SQL expression in a Blazor application without " + + "writing JavaScript."; + private readonly string[] _parcelLayerSql = { "Choose a SQL where clause...", "Roll_LandValue < 200000", "TaxRateArea = 10853", "Bedrooms5 > 0", diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SqlQuery.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SqlQuery.razor index 25851dc..f5d3119 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SqlQuery.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/SqlQuery.razor @@ -43,6 +43,21 @@ new("https://www.arcgis.com/home/item.html?id=c50de463235e4161b206d000587af18b", "Navigation BaseMap") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates running an ad-hoc " + + "SQL Query against a FeatureLayer from the ArcGIS Maps SDK for JavaScript exposed through " + + "GeoBlazor's MapView.QueryFeatures method, plus the FeatureLayer, SimpleFillSymbol, and " + + "PopupTemplate Razor components. The page shows a 2D navigation basemap centered on the Santa " + + "Monica Mountains in Los Angeles County. In the upper-right corner of the map a CustomOverlay " + + "hosts a dropdown of preset SQL where-clauses targeting the LA County parcels feature service, " + + "such as UseType = 'Residential', UseType = 'Government', UseType = 'Irrigated Farm', several " + + "TaxRateArea filters, and Roll_LandValue thresholds. Selecting a clause invokes QueryFeatures " + + "with that where expression, the current view extent, and a fixed set of OutFields, then renders " + + "the matching parcels as graphics styled with a semi-transparent blue SimpleFillSymbol and binds " + + "a PopupTemplate showing the parcel's APN, UseType, tax rate city, and land value. The sample is " + + "intended to demonstrate executing parameterized SQL queries against a hosted FeatureLayer and " + + "drawing the results in a Blazor application without writing JavaScript."; + public MapView? View { get; set; } public FeatureLayer? QueryFeatureLayer { get; set; } public SimpleFillSymbol? Symbol { get; set; } 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 6ea7e72..f1da29e 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 @@ -17,6 +17,21 @@ public partial class UniqueValueRenderers new("https://arcgis.com/home/item.html?id=7afec250e02845868db89c83949a672f", "OpenStreetMap Highways for North America") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the UniqueValueRenderer " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's UniqueValueRenderer, " + + "UniqueValueInfo, SimpleLineSymbol, and OrderByInfo Razor and C# components. The page shows a 2D " + + "basemap centered over the Houston, Texas area at a city-block scale, overlaid with an " + + "OpenStreetMap North America highways FeatureLayer. The renderer color-codes each road by its " + + "highway attribute, mapping motorways and trunks to thick pink and orange lines, primary roads " + + "to yellow, secondary to green, tertiary to blue, residential and unclassified streets to neutral " + + "grays, and pedestrian, footway, path, track, busway, raceway, construction, and proposed roads " + + "to a variety of dashed earth-tone styles; features are drawn in descending maxspeed order. Below " + + "the map a Toggle Legend button shows or hides a LegendWidget in the lower-left corner that lists " + + "every road type and its symbol under the heading Route Type. The sample is intended to " + + "demonstrate building a rich categorical renderer against a hosted FeatureLayer in a Blazor " + + "application without writing JavaScript."; + private static readonly Dictionary roadTypes = new() { // Major highways - wide, bold colors diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/VectorLayer.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/VectorLayer.razor index 3fe5db0..3c41af8 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/VectorLayer.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/VectorLayer.razor @@ -21,4 +21,15 @@ [ new("https://developers.arcgis.com/javascript/latest/add-a-vector-tile-layer/", "ArcGIS Maps SDK for JavaScript"), ]; + + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the VectorTileLayer " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's VectorTileLayer Razor " + + "component. The page shows a 2D map centered on the Santa Monica Mountains in Los Angeles County " + + "at zoom level 13. The base layer is an ArcGIS light-gray vector basemap, and on top of it the " + + "sample loads a hosted Santa Monica Mountains parcels VectorTileLayer from ArcGIS Online by URL. " + + "There are no widgets or controls above the map; the user can pan and zoom to explore the " + + "vector-tiled parcel boundaries, which scale crisply at any zoom level because they are rendered " + + "from vector tiles rather than raster images. The sample is intended to demonstrate adding a " + + "vector tile layer to a map by URL in a Blazor application without writing JavaScript."; } \ No newline at end of file diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WCSLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WCSLayers.razor index f24a7c9..527509b 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WCSLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WCSLayers.razor @@ -56,6 +56,20 @@ new("something", "NOAA Sea Surface Temperature Charts") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the WCSLayer (OGC " + + "Web Coverage Service) and RasterStretchRenderer from the ArcGIS Maps SDK for JavaScript exposed " + + "through GeoBlazor's WCSLayer, RasterStretchRenderer, MultipartColorRamp, AlgorithmicColorRamp, " + + "and DimensionalDefinition Razor components. The page shows a 2D light-gray basemap of the world. " + + "Above the map two buttons sit side by side and remain disabled until the map finishes rendering: " + + "the first toggles a colorized sea-temperature WCSLayer that is styled with a three-stop blue " + + "to cyan to yellow to red HSV color ramp using a standard-deviation stretch, and the second " + + "toggles a black-and-white version of the same layer. Both layers point at the NOAA sample " + + "ImageServer's WCS endpoint and are restricted to sea level (StdZ=0) at a fixed timestamp. While " + + "either layer is being added or removed the map cursor is set to wait. The sample is intended to " + + "demonstrate consuming an OGC WCS coverage and applying a custom raster color ramp in a Blazor " + + "application without writing JavaScript."; + private void OnViewRendered() => _mapRendered = true; private async Task AddRemoveWCSLayer(bool colorized) diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WFSLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WFSLayers.razor index f0f3ee5..738b2d0 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WFSLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WFSLayers.razor @@ -36,4 +36,18 @@ new("https://developers.arcgis.com/javascript/latest/sample-code/layers-wfs/", "ArcGIS Maps SDK for JavaScript"), new("https://geoportal.statistics.gov.uk/datasets/ons::counties-may-2023-boundaries-en-buc-2/about", "Office for National Statistics (UK)") ]; + + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the WFSLayer (OGC " + + "Web Feature Service) from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's " + + "WFSLayer, LayerListWidget, and PopupWidget Razor components. The page shows a 2D light-gray " + + "basemap centered on the United Kingdom at zoom level 5. Above the map are three short " + + "instruction paragraphs explaining that all you need is a WFS 2.0.0 service URL with GeoJSON " + + "output enabled and crediting the Office for National Statistics and Ordnance Survey. The map " + + "loads a single WFSLayer pointing at the May 2023 Counties of England feature type from the ONS " + + "WFS service, with PopupEnabled set so clicking any county opens its default popup. A " + + "LayerListWidget appears in the lower-left corner of the map and a generic PopupWidget with " + + "DefaultPopupTemplateEnabled is configured for the view. The sample is intended to demonstrate " + + "loading and interacting with a hosted OGC WFS service in a Blazor application without writing " + + "JavaScript."; } diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WMSLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WMSLayers.razor index bfd85f6..40a1444 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WMSLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WMSLayers.razor @@ -36,4 +36,16 @@ new("https://developers.arcgis.com/javascript/latest/sample-code/layers-wms/", "ArcGIS Maps SDK for JavaScript"), new("https://ows.terrestris.de/osm/service", "OpenStreetMap WMS") ]; + + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the WMSLayer (OGC " + + "Web Map Service) from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's WMSLayer " + + "and WMSSublayer Razor components. The page shows a 3D SceneView centered on Southeast Asia " + + "(roughly Bangladesh and Myanmar) viewed from a high altitude with a Web Mercator spatial " + + "reference. Instead of an ArcGIS basemap style, the basemap is built from a single WMSLayer " + + "pointing at the terrestris OpenStreetMap WMS service with the TOPO-WMS sublayer activated, " + + "rendering a topographic OpenStreetMap-derived globe. There are no controls or widgets above " + + "the map; the user can pan, zoom, and tilt to explore the globe. The sample is intended to " + + "demonstrate using an OGC WMS service as a 3D scene basemap in a Blazor application without " + + "writing JavaScript."; } \ No newline at end of file diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WMTSLayers.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WMTSLayers.razor index c83ca7d..216e711 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WMTSLayers.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WMTSLayers.razor @@ -40,6 +40,19 @@ new("https://www.ign.es/web/ign/portal", "Instituto Geográfico Nacional") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates the WMTSLayer (OGC " + + "Web Map Tile Service) from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's " + + "WMTSLayer, WMTSSublayer, Basemap, and BasemapToggleWidget Razor components. The page shows a 2D " + + "map centered on Madrid, Spain at roughly 1:4.6 million scale. Two Basemaps are configured, both " + + "built from WMTSLayers served by Spain's Instituto Geografico Nacional in KVP service mode: the " + + "default basemap uses the IGNBase-gris gray-tone reference layer, and the alternate basemap uses " + + "the MTN topographic raster layer; each basemap references a thumbnail GetTile request so the " + + "toggle button can render its preview. A BasemapToggleWidget in the lower-left corner of the map " + + "lets the user switch between the two IGN WMTS basemaps. The sample is intended to demonstrate " + + "consuming OGC WMTS tile services and exposing them through a basemap toggle in a Blazor " + + "application without writing JavaScript."; + private Basemap? _plainIGNBasemap; private Basemap? _orthoIGNBasemap; } \ No newline at end of file diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WebMaps.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WebMaps.razor index db0dc3c..c82cec9 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WebMaps.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WebMaps.razor @@ -66,6 +66,20 @@ new("https://developers.arcgis.com/javascript/latest/display-a-web-map/", "ArcGIS Maps SDK for JavaScript"), ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates loading a WebMap by " + + "PortalItem id from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's WebMap, " + + "PortalItem, ScaleBarWidget, and LegendWidget Razor components. The page shows a 2D MapView " + + "loaded from a hosted ArcGIS Online WebMap, including all of the WebMap's preconfigured layers, " + + "icons, popups, and styling. A ScaleBarWidget appears in the lower-left corner of the map and a " + + "LegendWidget appears in the upper-right corner. Below the map a Layers heading is followed by a " + + "table that lists every Layer in the WebMap with its type, title, and a Features cell. For each " + + "FeatureLayer the Features cell starts with a Load Features button; clicking it issues a " + + "QueryFeatures call with where 1=1 and OutFields *, then replaces the button with a scrollable " + + "list of feature names extracted from each graphic's attributes. The sample is intended to " + + "demonstrate displaying a hosted WebMap and inspecting its layers and features in a Blazor " + + "application without writing JavaScript."; + private async Task LoadLayer(FeatureLayer? featureLayer) { if (featureLayer is null) diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WebScenes.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WebScenes.razor index beba240..8220c03 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WebScenes.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/WebScenes.razor @@ -18,4 +18,16 @@ [ new("https://developers.arcgis.com/javascript/latest/display-a-web-scene/", "ArcGIS Maps SDK for JavaScript"), ]; + + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates loading a WebScene " + + "by PortalItem id from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's WebScene, " + + "PortalItem, SceneView, and LegendWidget Razor components. The page shows a 3D SceneView " + + "populated from a hosted ArcGIS Online WebScene, including all of the WebScene's preconfigured " + + "layers, icons, popups, ground elevation, lighting, and camera position. A LegendWidget sits in " + + "the upper-right corner of the scene and updates as layers come into view. There are no other " + + "controls above or around the map; the user can pan, zoom, tilt, and rotate the camera and " + + "click features to open their popups. The sample is intended to demonstrate displaying a " + + "complete hosted 3D WebScene with a single PortalItem reference in a Blazor application without " + + "writing JavaScript."; } \ No newline at end of file diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Widgets.razor b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Widgets.razor index 2eef9e6..84ba03c 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Widgets.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/Widgets.razor @@ -147,6 +147,23 @@ new("https://www.arcgis.com/home/item.html?id=c50de463235e4161b206d000587af18b", "Navigation BaseMap") ]; + public override string Description => + "This GeoBlazor sample, written in Blazor for .NET developers, demonstrates a gallery of widgets " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Razor components including " + + "LocateWidget, SearchWidget, BasemapToggleWidget, BasemapGalleryWidget, LegendWidget, " + + "ScaleBarWidget, HomeWidget, CompassWidget, BookmarksWidget, and MeasurementWidget. The page " + + "shows a 2D navigation basemap centered over the North Atlantic at zoom level 2. Above the map " + + "is a panel of ten labelled checkboxes for Locator, Search, Basemap Toggle, Basemap Gallery, " + + "Legend, Scale Bar, Home, Compass, Bookmarks, Distance Measurement, and Area Measurement 2D, " + + "plus an empty gallery-box div that hosts the Basemap Gallery outside the map when its checkbox " + + "is on. Toggling each checkbox shows or hides the corresponding widget, with the Locator and " + + "Home and Compass and measurement widgets anchored top-left, Search and Legend and Bookmarks " + + "anchored top-right, the Basemap Toggle anchored bottom-right (toggling to ArcGIS imagery), " + + "and the Scale Bar anchored bottom-left. Enabling Bookmarks programmatically loads three " + + "preset bookmarks (Angeles National Forest, Crystal Lake, Mt. Waterman) into the widget. The " + + "sample is intended to demonstrate composing and toggling many ArcGIS view widgets in a Blazor " + + "application without writing JavaScript."; + private MapView? MapView { get; set; } private async Task ToggleWidget(string widgetTypeName) 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..6ae471b 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor @@ -3,6 +3,22 @@ GeoBlazor Samples + + + + + + + + + + + + + + + +
@@ -25,14 +41,24 @@
@Body + @if (LayoutService.CurrentPage is { Description: { Length: > 0 } description }) + { +
+ About this sample +

@description

+
+ }
@code { + private static readonly System.Text.Json.JsonSerializerOptions JsonOptions = + new() { WriteIndented = false }; + [Inject] public required IConfiguration Configuration { get; set; } - + [Inject] public required NavigationManager NavigationManager { get; set; } @@ -76,6 +102,167 @@ private readonly string[] _btnTypes = ["btn-primary", "btn-secondary", "btn-accent"]; + private const string DefaultMetaDescription = + "Live, runnable GeoBlazor code samples — interactive maps, layers, widgets, and geospatial analysis " + + "in Blazor for .NET developers, powered by the ArcGIS Maps SDK for JavaScript."; + + private string CurrentSlug + { + get + { + string slug = NavigationManager.ToBaseRelativePath(NavigationManager.Uri); + int hashIndex = slug.IndexOf('#'); + if (hashIndex >= 0) slug = slug[..hashIndex]; + int queryIndex = slug.IndexOf('?'); + if (queryIndex >= 0) slug = slug[..queryIndex]; + return slug; + } + } + + private string MetaTitle + { + get + { + string slug = CurrentSlug; + return string.IsNullOrEmpty(slug) + ? "GeoBlazor Samples" + : $"{SlugToTitle(slug)} — GeoBlazor Sample"; + } + } + + private string MetaDescription + { + get + { + string? d = LayoutService.CurrentPage?.Description; + if (string.IsNullOrWhiteSpace(d)) + { + return DefaultMetaDescription; + } + + const int maxLen = 160; + if (d.Length <= maxLen) return d; + + int cut = d.LastIndexOf(' ', maxLen); + if (cut < 80) cut = maxLen; + return d[..cut].TrimEnd(',', ';', '.', ' ') + "…"; + } + } + + private string SchemaGraphJson + { + get + { + string pageUrl = NavigationManager.Uri; + string siteUrl = NavigationManager.BaseUri.TrimEnd('/'); + string slug = NavigationManager.ToBaseRelativePath(pageUrl); + int hashIndex = slug.IndexOf('#'); + if (hashIndex >= 0) slug = slug[..hashIndex]; + int queryIndex = slug.IndexOf('?'); + if (queryIndex >= 0) slug = slug[..queryIndex]; + string pageName = string.IsNullOrEmpty(slug) ? "GeoBlazor Samples" : SlugToTitle(slug); + + List graph = + [ + new Dictionary + { + ["@type"] = "WebSite", + ["@id"] = $"{siteUrl}/#website", + ["url"] = $"{siteUrl}/", + ["name"] = "GeoBlazor Samples", + ["description"] = "Live, runnable code samples for GeoBlazor — interactive maps, layers, widgets, and geospatial analysis in Blazor.", + ["publisher"] = new Dictionary { ["@id"] = "https://geoblazor.com/#organization" } + }, + new Dictionary + { + ["@type"] = "Organization", + ["@id"] = "https://geoblazor.com/#organization", + ["name"] = "GeoBlazor", + ["url"] = "https://geoblazor.com", + ["logo"] = "https://geoblazor.com/images/logos/GeoBlazor-Icon_250px.png", + ["sameAs"] = new[] + { + "https://github.com/dymaptic/GeoBlazor", + "https://www.nuget.org/packages/dymaptic.GeoBlazor.Core", + "https://discord.com/invite/x4QbXWb5" + } + }, + new Dictionary + { + ["@type"] = "SoftwareApplication", + ["@id"] = "https://geoblazor.com/#software", + ["name"] = "GeoBlazor", + ["description"] = "Native Blazor components for building interactive maps and GIS applications in .NET. Integrate the full power of ArcGIS into your Blazor WebAssembly and Server applications without JavaScript.", + ["applicationCategory"] = "DeveloperApplication", + ["applicationSubCategory"] = "Mapping API", + ["operatingSystem"] = ".NET 8, .NET 9, .NET 10", + ["url"] = "https://geoblazor.com", + ["downloadUrl"] = "https://www.nuget.org/packages/dymaptic.GeoBlazor.Core", + ["codeRepository"] = "https://github.com/dymaptic/GeoBlazor", + ["publisher"] = new Dictionary { ["@id"] = "https://geoblazor.com/#organization" } + }, + new Dictionary + { + ["@type"] = "WebPage", + ["@id"] = $"{pageUrl}#webpage", + ["url"] = pageUrl, + ["name"] = pageName, + ["isPartOf"] = new Dictionary { ["@id"] = $"{siteUrl}/#website" }, + ["about"] = new Dictionary { ["@id"] = "https://geoblazor.com/#software" } + } + ]; + + string? pageDescription = LayoutService.CurrentPage?.Description; + if (!string.IsNullOrWhiteSpace(pageDescription)) + { + ((Dictionary)graph[^1])["description"] = pageDescription; + } + + if (LayoutService.CurrentPage is not null) + { + Dictionary sourceCode = new() + { + ["@type"] = "SoftwareSourceCode", + ["@id"] = $"{pageUrl}#code", + ["url"] = pageUrl, + ["name"] = $"{pageName} — GeoBlazor Sample", + ["programmingLanguage"] = new[] { "C#", "Blazor" }, + ["codeRepository"] = "https://github.com/dymaptic/GeoBlazor-Samples", + ["isPartOf"] = new Dictionary { ["@id"] = $"{pageUrl}#webpage" }, + ["about"] = new Dictionary { ["@id"] = "https://geoblazor.com/#software" } + }; + + if (!string.IsNullOrWhiteSpace(pageDescription)) + { + sourceCode["description"] = pageDescription; + } + + graph.Add(sourceCode); + } + + Dictionary root = new() + { + ["@context"] = "https://schema.org", + ["@graph"] = graph + }; + + return System.Text.Json.JsonSerializer.Serialize(root, JsonOptions); + } + } + + private static string SlugToTitle(string slug) + { + string[] parts = slug.Split('-', StringSplitOptions.RemoveEmptyEntries); + for (int i = 0; i < parts.Length; i++) + { + if (parts[i].Length > 0) + { + parts[i] = char.ToUpperInvariant(parts[i][0]) + parts[i][1..]; + } + } + return string.Join(' ', parts); + } + public void Dispose() { HttpClient.Dispose(); diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor.css b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor.css index fac6a6b..fe03df9 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor.css +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor.css @@ -57,8 +57,9 @@ article.content { width: calc(100vw - 3rem); flex-grow: 1; margin: 0 auto; - padding-bottom: 10rem; + padding-bottom: 16rem; height: calc(100vh - 10rem); + overflow-y: auto; } @media (min-width: 1075px) { @@ -70,7 +71,7 @@ article.content { flex-direction: column; width: calc(100vw - 20rem); } - + .main-links { max-width: calc(100vw - 2rem); } @@ -78,7 +79,7 @@ article.content { article.content { padding-left: 2rem; padding-right: 1.5rem; - overflow-y: auto; + padding-bottom: 14rem; width: calc(100vw - 23rem); } } @@ -88,6 +89,10 @@ article.content { flex-direction: row-reverse; } + article.content { + padding-bottom: 4rem; + } + .main-links { width: 19.5rem; flex-direction: column; @@ -106,4 +111,53 @@ article.content { article.content { width: calc(100vw - 43rem); } -} \ No newline at end of file +} +.sample-description { + margin-top: 1.5rem; + padding: 0.75rem 1.5rem; + background-color: var(--background-grey-3); + border-radius: var(--box-radius); + font-size: 0.9rem; +} + +.sample-description summary { + cursor: pointer; + font-weight: 500; + color: var(--text-emphasis); + user-select: none; + display: flex; + align-items: center; + gap: 0.6rem; + list-style: none; + padding-left: 0.25rem; +} + +.sample-description summary::-webkit-details-marker { + display: none; +} + +.sample-description summary::before { + content: ""; + width: 0; + height: 0; + border-top: 0.3rem solid transparent; + border-bottom: 0.3rem solid transparent; + border-left: 0.45rem solid currentColor; + transition: transform 0.15s ease; + flex-shrink: 0; +} + +.sample-description[open] summary::before { + transform: rotate(90deg); +} + +.sample-description[open] summary { + margin-bottom: 0.5rem; +} + +.sample-description p { + margin: 0; + color: var(--text); + line-height: 1.5; +} + diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/NavMenu.razor.css b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/NavMenu.razor.css index bcc1ef4..8ae70cf 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/NavMenu.razor.css +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/NavMenu.razor.css @@ -18,7 +18,7 @@ overflow-y: auto; height: calc(100vh - 10rem); margin: 0; - padding: 1rem 0; + padding: 1rem 0 3.5rem 0; } #lower-nav-container a { diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/RenderModeSelector.razor.css b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/RenderModeSelector.razor.css index ec5d14c..729351b 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/RenderModeSelector.razor.css +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/RenderModeSelector.razor.css @@ -20,8 +20,3 @@ select { border: 1px solid black; } -@media (min-width: 1075px) { - .render-mode-selector-row { - left: 20rem; - } -} \ No newline at end of file diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/SamplePage.cs b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/SamplePage.cs index 0be2f90..032553c 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/SamplePage.cs +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/SamplePage.cs @@ -6,9 +6,18 @@ public abstract class SamplePage: ComponentBase { [Inject] public required LayoutService LayoutService { get; set; } - + public abstract List PageLinks { get; } + /// + /// A detailed, plain-text description of what this sample demonstrates. + /// Surfaced both in the rendered page (for users with JavaScript disabled and + /// for screen readers) and in the page's schema.org JSON-LD metadata so AI + /// agents and search crawlers can understand the sample without executing JS. + /// Override on each sample page; default is empty (no description rendered). + /// + public virtual string Description => string.Empty; + protected override void OnInitialized() { base.OnInitialized(); diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ApplyEdits.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ApplyEdits.razor index c34d349..93297ff 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ApplyEdits.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ApplyEdits.razor @@ -80,6 +80,18 @@ new("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/IncidentsReport/FeatureServer/0", "Incidents Report") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates the FeatureLayer.applyEdits " + + "workflow from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's FeatureLayer, FeatureFormWidget, " + + "and FeatureTemplatesWidget Razor components. The page shows a 2D dark-gray basemap centered on Redlands, " + + "California, displaying an incident-report FeatureLayer. A side panel pinned to the right of the map lists " + + "available incident templates rendered by the FeatureTemplatesWidget; the user picks a template and clicks " + + "the map to add a new incident point with that classification, or clicks an existing incident to load it " + + "into the FeatureFormWidget for attribute editing. The panel also exposes Update Incident Info and Delete " + + "Incident buttons that submit the form and call FeatureLayer.ApplyEdits to add, update, or delete features " + + "against the live feature service. The sample is intended to demonstrate end-to-end CRUD editing of a hosted " + + "FeatureLayer with template-driven creation and form-driven attribute updates."; + private async Task OnClick(ClickEvent clickEvent) { await UnselectFeature(); diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/Binning.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/Binning.razor index 34e0874..bdbe44e 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/Binning.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/Binning.razor @@ -80,6 +80,17 @@ new("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/ArcGIS/rest/services/NYC_motor_crashes/FeatureServer/0", "NYC Motor Crashes") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates the FeatureReductionBinning " + + "feature-reduction technique from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's " + + "FeatureReductionBinning Razor component. The page shows a 2D topographic map centered on New York City " + + "displaying 2020 motor-vehicle crash points aggregated into geohash bins; each bin is colored on a graduated " + + "ramp from light blue to dark red based on the number of crashes inside it and labeled with the crash count. " + + "A HomeWidget sits in the upper-left corner along with an ExpandWidget that, when opened, reveals a Toggle " + + "Binning button and a LegendWidget. Clicking Toggle Binning swaps the layer between the binned aggregate " + + "view and the raw crash points by calling FeatureLayer.SetFeatureReduction. The sample is intended to " + + "demonstrate how dense point data can be summarized into fixed bins for high-level pattern visualization."; + private async Task ToggleBinning() { _binning = !_binning; diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ClusterPieCharts.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ClusterPieCharts.razor index e936feb..6c98f2c 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ClusterPieCharts.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ClusterPieCharts.razor @@ -29,6 +29,17 @@ new("https://www.arcgis.com/home/item.html?id=433b5f7f524a4d1ebf3a9f8e1bd49ee0", "311 Calls") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates pie-chart cluster rendering " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's PieChartGenerator service together " + + "with the FeatureReductionCluster, PieChartRenderer, and PieChartMediaInfo Razor components. The page loads " + + "a WebMap of 311 service-call points and aggregates them into clusters; each cluster is drawn as a donut-shaped " + + "pie chart whose slices show the proportion of call categories within that cluster, with cluster_count labels " + + "in the center. An ExpandWidget in the upper-left corner opens a LegendWidget that explains the slice colors, " + + "and a HomeWidget allows the user to reset the view. Clicking a cluster opens a popup containing the " + + "cluster total, an embedded pie-chart media element, and a fields list. The sample is intended to demonstrate " + + "how to generate rich category-aware cluster visualizations and popups using GeoBlazor Pro's helper services."; + [Inject] public required LabelGenerator LabelGenerator { get; set; } diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/Clustering.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/Clustering.razor index de779cc..5893da6 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/Clustering.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/Clustering.razor @@ -87,6 +87,18 @@ new("https://www.arcgis.com/home/item.html?id=2b93b06dc0dc4e809d3c8db5cb96ba69", "World Countries Generalized Layer") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates point clustering on a " + + "GeoJSONLayer from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's GeoJSONLayer and " + + "FeatureReductionCluster Razor components. The page shows a polar 2D map (Alaska Polar Stereographic " + + "projection) of the world rendered in dark gray, displaying earthquake points from the USGS feed for the " + + "last month. Nearby earthquakes are reduced into light-blue circular clusters labeled with the count of " + + "events they represent, and individual quakes appear as triangles when zoomed in. A HomeWidget pinned in " + + "the upper-left corner returns to the starting extent, and an adjacent ExpandWidget opens a panel with an " + + "Enable/Disable Clustering toggle button and a LegendWidget. Clicking the toggle calls SetFeatureReduction " + + "to switch between aggregated clusters and raw points. The sample is intended to demonstrate spatial " + + "clustering of streamed GeoJSON data with custom cluster sizing and labeling."; + private async Task ToggleClustering() { _cluster = !_cluster; diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ClusteringPopups.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ClusteringPopups.razor index 4704277..376079b 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ClusteringPopups.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ClusteringPopups.razor @@ -62,6 +62,18 @@ new("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Places_of_Worship_India/FeatureServer/0", "Places of Worship") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates auto-generated cluster " + + "popups and labels from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's PopupTemplateGenerator " + + "and LabelGenerator services together with the FeatureReductionCluster Razor component. The page shows a 2D " + + "topographic map centered on India displaying a Places of Worship FeatureLayer aggregated into clusters. " + + "An ExpandWidget pinned in the upper-right corner contains a Filter by religion dropdown (All, Hindu, " + + "Christian, Muslim, Buddhist, Sikh, Jain), an Enable/Disable Clustering button, and a LegendWidget. Selecting " + + "a religion sets a feature filter on the layer view to show only matching places, and toggling clustering " + + "swaps the layer between aggregated and raw rendering. Clicking a cluster opens a generated popup describing " + + "the dominant attribute mix; clicking a single feature shows its name, religion, and denomination. The sample " + + "is intended to demonstrate generator-driven cluster styling with attribute filtering and popups."; + [Inject] public required PopupTemplateGenerator PopupTemplateGenerator { get; set; } [Inject] diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/CustomPopupContents.razor.cs b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/CustomPopupContents.razor.cs index edb4a6e..dc85a8d 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/CustomPopupContents.razor.cs +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/CustomPopupContents.razor.cs @@ -25,6 +25,18 @@ public partial class CustomPopupContents new("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/OverlaySchools/FeatureServer/0", "Private and Public US Schools") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates custom PopupTemplate content " + + "elements from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's CustomPopupContent, PopupWidget, " + + "and SearchWidget Razor components. The page shows a 2D topographic map of the contiguous United States " + + "displaying a FeatureLayer of public and private schools by state. Clicking a state opens a docked popup " + + "(pinned to the right edge) containing three custom content blocks: a GeoBlazor logo image at the top, an " + + "embedded SearchWidget that lets the user search by state name within the layer, and a dynamically generated " + + "HTML block that runs a server-side QueryService statistics query against a private-schools service and " + + "summarizes elementary, secondary, and combined private-school counts and average enrollment for the " + + "selected state. The sample is intended to demonstrate how to compose images, widgets, and code-driven HTML " + + "inside a single popup using the CreatorFunction extension point."; + [Inject] public required QueryService QueryService { get; set; } diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/DemographicData.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/DemographicData.razor index b4ffcc8..ee82f3e 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/DemographicData.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/DemographicData.razor @@ -45,6 +45,18 @@ new("https://www.arcgis.com/home/item.html?id=c50de463235e4161b206d000587af18b", "Navigation BaseMap") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates GeoEnrichment-style " + + "demographic queries from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's ArcGISRest " + + "service combined with the LocationService, GeometryEngine, and SearchWidget Razor components. The page " + + "shows a 2D navigation basemap initially centered on Milan, Italy. A SearchWidget pinned in the upper-right " + + "corner lets the user type a place name, and the user can also click any point on the map. On either action, " + + "the sample reverse-geocodes the location to a city name, draws a one-mile geodesic buffer polygon as a " + + "translucent overlay using GeometryEngine.GeodesicBuffer, calls ArcGISRest.QueryDemographicData to retrieve " + + "global demographic facts for that buffer, and opens a popup showing total population, male and female " + + "counts, and average household size. The sample is intended to demonstrate how to combine geocoding, " + + "buffering, and demographic enrichment into a single click-driven workflow."; + private MapView? View { get; set; } private Symbol? BufferSymbol { get; set; } diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/EditFeatureData.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/EditFeatureData.razor index ac7574d..1a6b612 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/EditFeatureData.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/EditFeatureData.razor @@ -34,4 +34,15 @@ new("https://developers.arcgis.com/javascript/latest/edit-feature-data/", "ArcGIS Maps SDK for JavaScript"), new("https://www.arcgis.com/home/item.html?id=979c6cc89af9449cbeb5342a439c6a76", "Light Gray Canvas BaseMap") ]; + + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates the Editor widget from the " + + "ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's EditorWidget Razor component. The page " + + "shows a 2D light-gray canvas basemap centered on the Santa Monica Mountains in southern California, " + + "displaying a hosted point FeatureLayer of user-contributed places. The EditorWidget appears as a docked " + + "panel in the upper-right corner with two modes: Select, which lets the user click an existing point to " + + "edit its attributes or geometry or delete it, and New Feature, which guides the user through adding a " + + "new point and entering its attributes via the widget's built-in form. All edits are submitted directly " + + "to the underlying feature service. The sample is intended to demonstrate the simplest possible drop-in " + + "editing experience for a hosted FeatureLayer using a single GeoBlazor component."; } \ No newline at end of file diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/GraphicsLegends.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/GraphicsLegends.razor index 275d3b7..d2ed760 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/GraphicsLegends.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/GraphicsLegends.razor @@ -1,4 +1,5 @@ @page "/graphics-legend" +@inherits SamplePage Graphics Legend

Graphics Legend

@@ -39,7 +40,26 @@ Style="width: 200px;" /> @code { - + + public override List PageLinks => + [ + new("https://docs.geoblazor.com/pages/widgets.html", "GeoBlazor Widgets Documentation") + ]; + + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates the GraphicsLegendWidget " + + "exclusive to GeoBlazor Pro, which builds a legend from arbitrary user-supplied Graphics rather than " + + "from a Layer's renderer. The page shows a 2D topographic basemap of the contiguous United States with " + + "five city graphics (San Diego, Seattle, San Francisco, New York, Boston) drawn with four different " + + "symbols: red and blue PictureMarkerSymbol stickpins, a green SimpleMarkerSymbol, and a translucent " + + "purple SimpleMarkerSymbol used twice with the same legend label. Three GraphicsLegendWidget instances " + + "appear simultaneously: one inside an ExpandWidget pinned to the lower-right corner of the map (with " + + "GroupBySymbol and SelectGraphics enabled), one as an overlay in the lower-left of the map (with " + + "GroupBySymbol and ToggleGraphics enabled), and one positioned outside the map below the view. Each " + + "legend uses a GraphicLabelTemplate to format entries from the graphic's attributes. The sample is " + + "intended to demonstrate flexible legend authoring from custom graphics in a Blazor application without " + + "writing JavaScript."; + private async Task OnViewRendered() { if (_firstRender) diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/GroupLayers.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/GroupLayers.razor index 00bae03..eed66e9 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/GroupLayers.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/GroupLayers.razor @@ -51,6 +51,18 @@ new("https://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9", "World Imagery Tile Layer") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates GroupLayer composition with " + + "blend modes and layer effects from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's GroupLayer, " + + "TileLayer, and GraphicsLayer Razor components. The page shows a 2D world imagery basemap initially centered " + + "on France, with the rest of the world blurred and grayscaled while France itself is rendered crisp and " + + "highlighted with a soft drop shadow. The highlight is achieved by stacking a GroupLayer that contains a " + + "second copy of the imagery and a destination-in-blended GraphicsLayer holding the country polygon, then " + + "applying SetEffect to both the base imagery and the GroupLayer. A small instruction banner pinned to the " + + "upper-right of the map reads Click on a country; clicking anywhere queries a hidden countries FeatureLayer, " + + "moves the highlight to the clicked country, and re-applies the effects. The sample is intended to demonstrate " + + "how blend modes, effects, and grouped layers can produce visually rich spatial focus treatments."; + private async Task OnLayerViewCreate(LayerViewCreateEvent createEvent) { if (createEvent.Layer?.Id == _worldImagery?.Id && !_worldImageryPopupsDisabled) diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/HighlightFeaturesByGeometry.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/HighlightFeaturesByGeometry.razor index 766063c..85a4caf 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/HighlightFeaturesByGeometry.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/HighlightFeaturesByGeometry.razor @@ -82,6 +82,18 @@ new("https://www.arcgis.com/home/item.html?id=d72ab790752142bd9dfb190c79d6582b", "National Park Service Establishments") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates spatial selection by drawn " + + "geometry from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's SketchWidget and " + + "FeatureTableWidget Razor components combined with FeatureLayerView feature effects. The page shows a 2D " + + "Albers Equal Area projection map of the contiguous United States with a custom cream-and-gray basemap and " + + "a National Park Service points-of-interest FeatureLayer overlaid. A SketchWidget pinned in the upper-left " + + "corner provides a rectangle drawing tool, and a Clear Selection button sits beside it. Below the map is a " + + "FeatureTableWidget that lists every NPS feature. When the user drags a rectangle on the map, the sample " + + "queries the layer view for intersecting features, blurs and dims the rest using a FeatureEffect, highlights " + + "the selected rows in the table, and synchronizes hovering rows with on-map highlights. The sample is " + + "intended to demonstrate coordinated spatial-and-tabular selection driven by user-drawn geometry."; + private async Task OnViewRendered() { if (_firstRender) diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ImageryGroupBlend.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ImageryGroupBlend.razor index cf0cdd1..3efdef3 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ImageryGroupBlend.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ImageryGroupBlend.razor @@ -70,6 +70,18 @@ new("https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer", "World Elevation Terrain 3D") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates ImageryTileLayer rendering " + + "with raster stretch from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's ImageryTileLayer, " + + "GroupLayer, RasterStretchRenderer, and SliderWidget Razor components. The page shows a 2D map centered on " + + "the Tibetan Plateau with a GroupLayer that blends World Imagery underneath a World Elevation 3D ImageryTileLayer " + + "using a destination-in blend mode. A LayerListWidget in the upper-right corner lets the user expand the " + + "elevation layer and reveal a stretch-rendering panel containing a stretch-type dropdown (Min-Max or Standard " + + "Deviation), a two-handle SliderWidget that adjusts the active stretch values in meters or standard deviations, " + + "and a checkbox that toggles the GroupLayer's blend mode between DestinationIn and Normal. A BasemapToggleWidget " + + "in the lower-left switches between light-gray and dark-gray basemaps. The sample is intended to demonstrate " + + "interactive raster styling and blending of elevation data over imagery."; + private async Task OnLayerViewCreated(LayerViewCreateEvent createEvent) { if (createEvent.Layer?.Id == _layer!.Id diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/LengthAndArea.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/LengthAndArea.razor index ca9c004..7f1b06c 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/LengthAndArea.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/LengthAndArea.razor @@ -59,6 +59,19 @@ new("https://www.arcgis.com/home/item.html?id=867895a71a1840399476fc717e76bb43", "Mid-Century BaseMap") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates planar and geodesic " + + "measurement with the GeometryEngine from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's " + + "GeometryEngine service together with the SketchWidget and ScaleBarWidget Razor components. The page shows " + + "a 2D mid-century-themed basemap centered on the eastern Atlantic with a starting blue rectangle drawn over " + + "northwest Africa to seed the calculation. A SketchWidget in the upper-right corner provides Polyline, " + + "Polygon, and Rectangle drawing tools so the user can replace or modify the shape; a ScaleBarWidget sits in " + + "the lower-right corner. Whenever a sketch is created or updated, the sample calls GeometryEngine.GeodesicArea, " + + "PlanarArea, GeodesicLength, or PlanarLength as appropriate and writes the resulting square-kilometer or " + + "kilometer values into a measurements overlay docked at the bottom of the map. The sample is intended to " + + "demonstrate how planar and geodesic measurement diverge for large regions when calculated alongside live " + + "user input."; + private async Task OnViewRendered() { if (!_firstRender) diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/OGCFeatureLayers.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/OGCFeatureLayers.razor index b504b21..f5c51e9 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/OGCFeatureLayers.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/OGCFeatureLayers.razor @@ -79,6 +79,18 @@ new("https://demo.ldproxy.net/vineyards", "Vineyards in Rhineland-Palatinate, Germany") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates the OGC API Features " + + "client from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's OGCFeatureLayer Razor component, " + + "along with grouped ExpandWidgets. The page shows a 2D light-gray basemap zoomed into the Rhineland-Palatinate " + + "wine region of Germany, displaying vineyard polygons fetched from a public OGC API Features endpoint and " + + "rendered with a green Mangrove WebStyleSymbol and italic name labels at large scales. Two ExpandWidgets in " + + "the upper-left corner share a group so only one is open at a time: a question-mark button reveals a Wineries " + + "info panel, and a filter button reveals an area filter with three clickable rows (greater than 100 hectares, " + + "50-100 hectares, less than 50 hectares). Selecting a filter applies a FeatureEffect that fades out non-matching " + + "vineyards, and clicking a vineyard opens a docked popup describing its name, area, village, region, and " + + "subregion. The sample is intended to demonstrate consuming an OGC service with custom labeling and filtering."; + private async Task OnViewRendered() { if (_firstRender) diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/PopupEdit.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/PopupEdit.razor index b7f5714..53209dc 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/PopupEdit.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/PopupEdit.razor @@ -66,6 +66,19 @@ new("https://www.arcgis.com/home/item.html?id=67372ff42cd145319639a99152b15bc3", "Topographic Vector BaseMap") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates a custom popup edit action " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's PopupWidget, EditorWidget, " + + "PopupTemplate, and ActionButton Razor components. The page shows a 2D topographic basemap centered on " + + "El Paso, Texas, displaying a recreation-trails FeatureLayer. An ExpandWidget in the upper-left corner " + + "carries a help panel explaining the workflow. Clicking a trail opens a popup whose content is generated " + + "by a content function that color-codes the difficulty level (green for easy, purple for medium, red for " + + "hard) and shows attachments; the popup also exposes a custom Edit feature ActionButton with a pencil " + + "icon. Clicking that action closes the popup, opens the EditorWidget docked in the upper-right corner, " + + "and starts an attribute-editing workflow scoped to the clicked feature. When the editor is dismissed, " + + "the popup re-opens with refreshed values. The sample is intended to demonstrate orchestrating popups and " + + "the editor through a single in-popup action."; + private ValueTask DifficultyLevel(Graphic graphic) { AttachmentsPopupContent attachmentsElement = diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/PrintWidgets.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/PrintWidgets.razor index a4d8e30..1a67994 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/PrintWidgets.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/PrintWidgets.razor @@ -26,4 +26,15 @@ new("https://developers.arcgis.com/javascript/latest/sample-code/widgets-print/", "ArcGIS Maps SDK for JavaScript"), new("https://www.arcgis.com/home/item.html?id=d6d830a7184f4971b8a2f42cd774d9a7", "Missing Migrants Around the Globe Class Breaks Web Map") ]; + + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates the Print widget from the " + + "ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's PrintWidget Razor component. The page loads " + + "the Missing Migrants Around the Globe WebMap into a 2D MapView and pins a PrintWidget in the upper-right " + + "corner. The PrintWidget panel lets the user pick a layout template, set a title, choose an output file " + + "format (PDF, PNG, JPG, and others), toggle whether to preserve map extent or map scale, and access advanced " + + "options including localized date insertion and per-template custom text elements discovered from the print " + + "GPServer's Get Layout Templates Info task. Clicking Print sends the request to the print service and " + + "produces a downloadable file. The sample is intended to demonstrate generating server-side printable " + + "exports of a WebMap directly from the browser."; } diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ProBookmarks.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ProBookmarks.razor index 1d6c6e1..9608336 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ProBookmarks.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ProBookmarks.razor @@ -54,6 +54,18 @@ new("https://developers.arcgis.com/javascript/latest/api-reference/esri-WebMap.html", "ArcGIS Maps SDK for JavaScript WebMap reference") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates the Bookmarks and TimeSlider " + + "widgets from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's BookmarksWidget and Pro's " + + "TimeSliderWidget Razor components. The page loads a hurricanes-themed WebMap into a 2D MapView. An " + + "ExpandWidget pinned in the upper-right corner contains a draggable BookmarksWidget with edit and add-bookmark " + + "buttons, and another ExpandWidget in the upper-left holds a card-style LegendWidget. A TimeSliderWidget " + + "anchored at the bottom-left animates the hurricane data over time in a looping time-window mode. A Clear " + + "filter button overlays the bottom-right. Selecting a bookmark applies a FeatureEffect that grays out " + + "non-matching hurricane features so the named storm stands out, and a list below the map demonstrates " + + "reactive binding to the BookmarksCollection's after-add event. The sample is intended to demonstrate " + + "combining bookmarks, timeline animation, and reactive collection events in one map."; + private async Task OnViewRendered() { if (!_handlerRegistered) diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ProWidgets.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ProWidgets.razor index 3750cb5..aae0d09 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ProWidgets.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/ProWidgets.razor @@ -218,6 +218,18 @@ new("https://www.arcgis.com/home/item.html?id=c50de463235e4161b206d000587af18b", "Navigation BaseMap") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates a gallery of map widgets " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's BasemapToggleWidget, BasemapGalleryWidget, " + + "SearchWidget, LegendWidget, ScaleBarWidget, HomeWidget, LocateWidget, CompassWidget, BookmarksWidget, " + + "MeasurementWidget, and Pro's EditorWidget, SketchWidget, and TrackWidget Razor components. Above the map " + + "is a grid of labeled checkboxes grouped into Core widgets and a separate GeoBlazor Pro section (Editor, " + + "Sketch, Track). Toggling a checkbox adds or removes the corresponding widget on the 2D navigation basemap " + + "centered on the Atlantic, demonstrating overlay positioning at the four corners; the BasemapGallery is " + + "rendered into a separate gallery-box container outside the map to show off-map placement. The Bookmarks " + + "checkbox seeds three preset Angeles National Forest bookmarks. The sample is intended to demonstrate the " + + "breadth of widgets available in GeoBlazor and how each can be enabled or repositioned independently."; + [Inject] public required NavigationManager NavigationManager { get; set; } private async Task ToggleWidget(string widgetTypeName) diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/RoutesAndDirections.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/RoutesAndDirections.razor index 5dfd17f..18c85f1 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/RoutesAndDirections.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/RoutesAndDirections.razor @@ -42,6 +42,18 @@ new("https://www.arcgis.com/home/item.html?id=4f2e99ba65e34bb8af49733d9778fb8e", "Human Geography Dark BaseMap") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates routing and turn-by-turn " + + "directions from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's RouteService together " + + "with the GraphicsLayer and CustomOverlay Razor components. The page shows a 2D dark human-geography basemap " + + "centered on Redlands, California, with a Clear button positioned above the map. The user clicks two or " + + "more locations on the map; each click drops a white cross stop marker, and once at least two stops exist " + + "the sample calls RouteService.Solve against the world routing service and renders the resulting route as " + + "a translucent blue polyline. A directions panel pinned in the upper-right corner of the map lists each " + + "maneuver with its distance in miles, and the Clear button removes all stops, the route, and the directions. " + + "The sample is intended to demonstrate point-and-click route solving and step-by-step driving directions " + + "with the ArcGIS World Route service."; + [Inject] public required RouteService RouteService { get; set; } diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SearchCustomSource.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SearchCustomSource.razor index ee78751..5084ee1 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SearchCustomSource.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SearchCustomSource.razor @@ -36,6 +36,18 @@ new("https://www.arcgis.com/home/item.html?id=55ebf90799fa4a3fa57562700a68c405", "Streets BaseMap") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates a custom search source " + + "from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's SearchWidget and LocatorSearchSource " + + "Razor components combined with GeoBlazor Pro's ArcGISRest service. The page shows a 2D streets basemap " + + "initially centered on metropolitan France. A SearchWidget pinned in the upper-right corner exposes a single " + + "non-default source whose Placeholder reads example: 8 Boulevard du Port. As the user types, the sample " + + "calls a French national address API (api-adresse.data.gouv.fr) via ArcGISRest.Request to fetch suggestions " + + "biased to the current map center; selecting a result calls the same API with reverse geocoding and produces " + + "a SearchResult whose extent is computed by buffering the returned point with GeometryEngine.GeodesicBuffer. " + + "The sample is intended to demonstrate plugging a third-party REST geocoder into the SearchWidget through " + + "custom suggestion and result handlers."; + private void OnExtentChanged(Extent extent) { _center = _view!.Center ?? _center; diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SketchQuery.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SketchQuery.razor index 51d0ac3..8ed76c5 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SketchQuery.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SketchQuery.razor @@ -48,6 +48,18 @@ new("https://www.arcgis.com/home/item.html?id=867895a71a1840399476fc717e76bb43", "Mid-Century BaseMap") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates spatial intersection queries " + + "driven by user sketches from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's SketchWidget " + + "and the MapView.QueryFeatures convenience method together with a FeatureLayer of LA County parcels. The " + + "page shows a 2D mid-century-themed basemap centered on the Santa Monica Mountains. A SketchWidget pinned " + + "in the upper-right corner lets the user draw and reshape a polygon on top of an empty GraphicsLayer. " + + "Whenever a sketch completes or is updated, the sample sets the polygon as the geometry on a Query whose " + + "spatial relationship is Intersects, runs it against the parcels FeatureLayer, and renders the matching " + + "parcels with a translucent blue fill symbol. Clicking any rendered parcel opens a popup showing its APN, " + + "use type, land value, and tax-rate city. The sample is intended to demonstrate spatial selection of an " + + "external feature service driven by free-form sketches."; + public MapView? View { get; set; } public FeatureLayer? ParcelLayer { get; set; } public PopupTemplate? PopupTemplate { get; set; } diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SpatialRelationships.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SpatialRelationships.razor index 78b3bb5..0a5c244 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SpatialRelationships.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/SpatialRelationships.razor @@ -74,6 +74,18 @@ new("https://www.arcgis.com/home/item.html?id=358ec1e175ea41c3bf5c68f0da11ae2b", "Dark Gray Canvas BaseMap") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates the GeometryEngine's " + + "topological relationship predicates from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's " + + "GeometryEngine service together with the SketchWidget Razor component. The page shows a 2D dark-gray canvas " + + "basemap centered on the Santa Monica Mountains, prepopulated with a polyline and a polygon graphic that " + + "the user can drag, reshape, or replace. A SketchWidget in the upper-right corner provides update and create " + + "tools (polyline, polygon, rectangle, circle) with snapping enabled. A Spatial relationships overlay docked " + + "in the lower-right lists every relationship from the SpatialRelationship enum (Contains, Crosses, Disjoint, " + + "EqualTo, Intersects, Overlaps, Touches, Within), each updating to true or false in real time as the user " + + "edits geometry, with currently true relationships rendered in bold. The sample is intended to demonstrate " + + "how GeometryEngine evaluates each topological predicate between two geometries."; + private async Task OnViewRendered() { if (_firstRender) diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/StyledGeoJSONLayers.razor.cs b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/StyledGeoJSONLayers.razor.cs index 424c944..4456df9 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/StyledGeoJSONLayers.razor.cs +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/StyledGeoJSONLayers.razor.cs @@ -20,6 +20,18 @@ public partial class StyledGeoJSONLayers new("https://github.com/mapbox/simplestyle-spec/tree/master/1.1.0", "Mapbox SimpleStyle Spec") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates SimpleStyle / GeoJSON CSS " + + "rendering of inline GeoJSON from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's " + + "ProGeoJSONLayer Razor component. The page shows a 2D navigation basemap centered on Seattle. Above the " + + "map are four checkbox toggles for the layer set: Tourist Points, Neighborhoods, Transportation Routes, " + + "and Public Services. Each toggle controls a ProGeoJSONLayer whose source is an embedded GeoJSON feature " + + "collection that uses Mapbox-style marker-color, marker-size, marker-symbol, fill, fill-opacity, stroke, " + + "stroke-width, and stroke-dasharray properties; the layer renders these directly when ApplyStyles is true. " + + "Below the map is a row of feature buttons, one per visible feature, color-matched to the styling. Clicking " + + "a button highlights the feature, zooms to a buffered extent of its geometry, and opens its default popup. " + + "The sample is intended to demonstrate styling inline GeoJSON without writing a renderer."; + [Inject] public required GeometryEngine GeometryEngine { get; set; } diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/Swipe.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/Swipe.razor index d243b7a..adfb9b1 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/Swipe.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/Swipe.razor @@ -35,6 +35,17 @@ new("https://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/WV03_Kilauea_20180519_NearInfrared/MapServer", "Near Infrared Tile Layer") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates the Swipe widget from the " + + "ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's SwipeWidget Razor component. The page shows " + + "a 2D topographic basemap centered on the 2018 Kilauea eruption on the Big Island of Hawaii, with two " + + "WorldView-3 TileLayers stacked on top: a near-infrared image and a shortwave-infrared image of the same " + + "scene. The SwipeWidget overlays a draggable vertical divider initially positioned at 30 percent of the " + + "view width; the near-infrared image fills the leading (left) side and the shortwave-infrared image fills " + + "the trailing (right) side. Dragging the handle reveals more of one layer or the other. An ExpandWidget in " + + "the upper-right corner contains a LayerListWidget for toggling layer visibility. The sample is intended " + + "to demonstrate side-by-side comparison of two coregistered raster layers with an interactive swipe handle."; + private TileLayer? _shortWaveLayer; private TileLayer? _nearInfraredLayer; } \ No newline at end of file diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/TimeSlider.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/TimeSlider.razor index 918b1cb..304a103 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/TimeSlider.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/TimeSlider.razor @@ -36,6 +36,18 @@ new("https://www.arcgis.com/home/item.html?id=f9e9283b9c9741d09aad633f68758bf6", "National Weather Service Precipitation Forecast") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates the TimeSlider widget from " + + "the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's TimeSliderWidget Razor component. The " + + "page shows a 2D navigation basemap centered on the contiguous United States, with a National Weather " + + "Service precipitation forecast FeatureLayer added programmatically when the view first renders. A " + + "TimeSliderWidget docked at the bottom of the map is configured for a moving time-window mode with looping " + + "playback, and uses a TickConfig with four percent-based tick stops at 12.5, 37.5, 62.5, and 87.5 percent " + + "of the slider's range. After the layer view is created, the sample reads the layer's TimeInfo and calls " + + "SetFullTimeExtent and SetStops with the layer's natural interval so the slider snaps to forecast steps. " + + "Pressing play animates the precipitation through time. The sample is intended to demonstrate driving " + + "temporal animation of a time-aware FeatureLayer."; + private async Task OnViewRendered() { if (!_mapView!.Map!.Layers.Contains(_featureLayer!)) diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/UpdateFeatureAttributes.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/UpdateFeatureAttributes.razor index fb26e28..a6f7f8a 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/UpdateFeatureAttributes.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/UpdateFeatureAttributes.razor @@ -76,6 +76,19 @@ new("https://www.arcgis.com/home/item.html?id=449887ea7d60429fbf6f0c67881f2758", "Building Damage Assessments") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates a grouped FeatureForm-driven " + + "attribute update workflow from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's FormTemplate, " + + "GroupElement, FieldElement, and Pro's FeatureFormWidget Razor components. The page shows a 2D topographic " + + "basemap zoomed in on a Naperville, Illinois neighborhood used for damage assessments. Initially an info " + + "card pinned in the upper-right corner instructs the user to select a feature; clicking a building point " + + "highlights the feature and replaces the card with a scrollable form panel containing four collapsible " + + "groups (Inspector Information, Contact Information, Insurance coverage, Insurance type information) " + + "rendered sequentially by the FeatureFormWidget, plus an Update Assessment button. Submitting the form " + + "writes the changed attribute values back through FeatureLayer.ApplyEdits. A FormTemplateExpressionInfo " + + "named alwaysHidden hides the inspector email field. The sample is intended to demonstrate complex grouped " + + "form editing tied to a single feature."; + private async Task OnClick(ClickEvent clickEvent) { if (_highlightHandle is not null) diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/WFSUtils.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/WFSUtils.razor index 674bf8b..e0bd020 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/WFSUtils.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/WFSUtils.razor @@ -58,6 +58,18 @@ new("https://geoportal.statistics.gov.uk/datasets/ons::counties-may-2023-boundaries-en-buc-2/about", "Office for National Statistics (UK)") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates browsing and consuming " + + "OGC Web Feature Services from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's WfsUtils " + + "service together with the WFSLayer, LayerListWidget, and PopupWidget Razor components. The page shows a " + + "2D light-gray basemap centered on the United Kingdom. A panel pinned in the upper-right corner contains " + + "a label OGC WFS endpoint, a text input prefilled with the UK Office for National Statistics counties " + + "WFS URL, and a Get Capabilities button. Clicking the button calls WfsUtils.GetCapabilities to issue a " + + "GetCapabilities request and renders the returned feature types as a clickable list, with a calcite-loader " + + "shown during fetch and a warning notice if the service does not support WFS 2.0.0 with GeoJSON output. " + + "Selecting a feature type adds it to the map as a WFSLayer and zooms to its extent. The sample is intended " + + "to demonstrate runtime discovery of WFS feature types and dynamic layer addition."; + [Inject] public required WfsUtils Utils { get; set; } diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/WebStyleSymbols.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/WebStyleSymbols.razor index a164246..6629717 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/WebStyleSymbols.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/WebStyleSymbols.razor @@ -84,6 +84,19 @@ new("http://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/LA_County_Points_of_Interest/FeatureServer/0", "LA County Points of Interest") ]; + public override string Description => + "This GeoBlazor Pro sample, written in Blazor for .NET developers, demonstrates 2D Web Style Symbols rendered " + + "through a UniqueValueRenderer from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor's " + + "WebStyleSymbol, UniqueValueRenderer, SizeVariable, and BookmarksWidget Razor components. The page shows " + + "a 2D light-gray basemap centered on the San Fernando Valley area of Los Angeles County, displaying a " + + "points-of-interest FeatureLayer. A UniqueValueRenderer with a long Arcade ValueExpression maps each " + + "feature's category to one of twenty-five WebStyleSymbol icons (post-office, atm, place-of-worship, park, " + + "school, hospital, fire-station, library, museum, airport, and so on) drawn from the Esri 2D Point Symbols " + + "style. A SizeVariable scales the icons from 20 down to 1 pixel based on view scale. A BookmarksWidget in " + + "the upper-left corner offers Angeles National Forest, Crystal Lake, and San Fernando bookmarks, and a " + + "LegendWidget in the lower-right shows the category-to-icon mapping. The sample is intended to demonstrate " + + "category-based pictographic styling at multiple scales."; + private UniqueValueInfo[] RendererInfos => _symbolCats.Select(symCat => new UniqueValueInfo(symCat, new WebStyleSymbol(styleName: "Esri2DPointSymbolsStyle", name: symCat), From d23dd46d5a9f003272d5dfb1654ec7bd4028410f Mon Sep 17 00:00:00 2001 From: Maggie Moeller Date: Fri, 1 May 2026 12:30:55 -0400 Subject: [PATCH 2/5] Address Copilot PR review feedback - Canonicalize page URLs used in @id, url, isPartOf, and og:url by stripping query string and fragment from NavigationManager.Uri. Without this, hitting /compass-widget?foo=bar produced an invalid schema.org @id of "/compass-widget?foo=bar#webpage" (two # in one URL) and unstable canonical URLs across query-string variations. - Clear LayoutService.CurrentPage on every navigation by subscribing to NavigationManager.LocationChanged in MainLayout. SamplePage routes re-set CurrentPage in OnInitialized; non-SamplePage routes (Home, NotFound) now leave it null so the layout no longer leaks the previous sample's action buttons, About-this-sample block, meta description, or JSON-LD onto pages that aren't sample pages. - Fix grammar in WFSUtils description: "a label OGC WFS endpoint" to "a labeled OGC WFS endpoint". Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Shared/LayoutService.cs | 7 ++++ .../Shared/MainLayout.razor | 39 ++++++++++++------- .../Pages/WFSUtils.razor | 2 +- 3 files changed, 32 insertions(+), 16 deletions(-) diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/LayoutService.cs b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/LayoutService.cs index cc9fc69..9bf823e 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/LayoutService.cs +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/LayoutService.cs @@ -11,4 +11,11 @@ public void SetCurrentPage(SamplePage page) CurrentPage = page; OnPageChanged?.Invoke(); } + + public void ClearCurrentPage() + { + if (CurrentPage is null) return; + CurrentPage = null; + OnPageChanged?.Invoke(); + } } \ No newline at end of file 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 b749a18..7f7bdd0 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor @@ -8,7 +8,7 @@ - + @@ -80,8 +80,18 @@ protected override void OnInitialized() { base.OnInitialized(); - + LayoutService.OnPageChanged += StateHasChanged; + NavigationManager.LocationChanged += OnLocationChanged; + } + + private void OnLocationChanged(object? sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e) + { + // Clear before the new page renders. If the new page inherits SamplePage, + // its OnInitialized will set CurrentPage again. Pages that don't inherit + // SamplePage (Home, NotFound, etc.) leave it null so the layout doesn't + // render stale per-page metadata. + LayoutService.ClearCurrentPage(); } protected override async Task OnAfterRenderAsync(bool firstRender) @@ -102,19 +112,21 @@ "Live, runnable GeoBlazor code samples — interactive maps, layers, widgets, and geospatial analysis " + "in Blazor for .NET developers, powered by the ArcGIS Maps SDK for JavaScript."; - private string CurrentSlug + private string CanonicalPageUrl { get { - string slug = NavigationManager.ToBaseRelativePath(NavigationManager.Uri); - int hashIndex = slug.IndexOf('#'); - if (hashIndex >= 0) slug = slug[..hashIndex]; - int queryIndex = slug.IndexOf('?'); - if (queryIndex >= 0) slug = slug[..queryIndex]; - return slug; + string uri = NavigationManager.Uri; + int hashIndex = uri.IndexOf('#'); + if (hashIndex >= 0) uri = uri[..hashIndex]; + int queryIndex = uri.IndexOf('?'); + if (queryIndex >= 0) uri = uri[..queryIndex]; + return uri; } } + private string CurrentSlug => NavigationManager.ToBaseRelativePath(CanonicalPageUrl); + private string MetaTitle { get @@ -149,13 +161,9 @@ { get { - string pageUrl = NavigationManager.Uri; + string pageUrl = CanonicalPageUrl; string siteUrl = NavigationManager.BaseUri.TrimEnd('/'); - string slug = NavigationManager.ToBaseRelativePath(pageUrl); - int hashIndex = slug.IndexOf('#'); - if (hashIndex >= 0) slug = slug[..hashIndex]; - int queryIndex = slug.IndexOf('?'); - if (queryIndex >= 0) slug = slug[..queryIndex]; + string slug = CurrentSlug; string pageName = string.IsNullOrEmpty(slug) ? "GeoBlazor Samples" : SlugToTitle(slug); List graph = @@ -263,6 +271,7 @@ { HttpClient.Dispose(); LayoutService.OnPageChanged -= StateHasChanged; + NavigationManager.LocationChanged -= OnLocationChanged; } } \ No newline at end of file diff --git a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/WFSUtils.razor b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/WFSUtils.razor index e0bd020..0898080 100644 --- a/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/WFSUtils.razor +++ b/samples/pro/dymaptic.GeoBlazor.Pro.Sample.Shared/Pages/WFSUtils.razor @@ -63,7 +63,7 @@ "OGC Web Feature Services from the ArcGIS Maps SDK for JavaScript exposed through GeoBlazor Pro's WfsUtils " + "service together with the WFSLayer, LayerListWidget, and PopupWidget Razor components. The page shows a " + "2D light-gray basemap centered on the United Kingdom. A panel pinned in the upper-right corner contains " + - "a label OGC WFS endpoint, a text input prefilled with the UK Office for National Statistics counties " + + "a labeled OGC WFS endpoint, a text input prefilled with the UK Office for National Statistics counties " + "WFS URL, and a Get Capabilities button. Clicking the button calls WfsUtils.GetCapabilities to issue a " + "GetCapabilities request and renders the returned feature types as a clickable list, with a calcite-loader " + "shown during fetch and a warning notice if the service does not support WFS 2.0.0 with GeoJSON output. " + From 4cee8380ba10ddc9e86be873336811794d9bcfee Mon Sep 17 00:00:00 2001 From: Maggie Moeller Date: Fri, 1 May 2026 15:11:44 -0400 Subject: [PATCH 3/5] Address second round of Copilot PR review feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MetaTitle only adds the "— GeoBlazor Sample" suffix when on an actual sample page (LayoutService.CurrentPage is not null). Routes like /not-found previously advertised themselves as "Not Found — GeoBlazor Sample". - SlugToTitle takes the last path segment before kebab-splitting, so multi-segment routes like /source-code/{slug} produce a clean leaf-only title instead of leaking a / into the rendered title. - Remove HttpClient.Dispose() from MainLayout.Dispose. Disposing the DI-injected HttpClient broke any later component using the same instance with ObjectDisposedException; DI manages lifetime. - Clear the disclosure marker via summary::marker in addition to the WebKit pseudo. Without this, Firefox showed both the native marker and the custom CSS triangle. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Shared/MainLayout.razor | 12 ++++++++---- .../Shared/MainLayout.razor.css | 4 ++++ 2 files changed, 12 insertions(+), 4 deletions(-) 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 7f7bdd0..5fe5762 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor @@ -132,9 +132,11 @@ get { string slug = CurrentSlug; - return string.IsNullOrEmpty(slug) - ? "GeoBlazor Samples" - : $"{SlugToTitle(slug)} — GeoBlazor Sample"; + if (string.IsNullOrEmpty(slug)) return "GeoBlazor Samples"; + string title = SlugToTitle(slug); + return LayoutService.CurrentPage is not null + ? $"{title} — GeoBlazor Sample" + : title; } } @@ -256,6 +258,9 @@ private static string SlugToTitle(string slug) { + int lastSlash = slug.LastIndexOf('/'); + if (lastSlash >= 0) slug = slug[(lastSlash + 1)..]; + string[] parts = slug.Split('-', StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < parts.Length; i++) { @@ -269,7 +274,6 @@ public void Dispose() { - HttpClient.Dispose(); LayoutService.OnPageChanged -= StateHasChanged; NavigationManager.LocationChanged -= OnLocationChanged; } diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor.css b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor.css index fe03df9..d2f1f1f 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor.css +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor.css @@ -136,6 +136,10 @@ article.content { display: none; } +.sample-description summary::marker { + content: ""; +} + .sample-description summary::before { content: ""; width: 0; From 0c57335b3007657b4812fbdf521d76629537f5f1 Mon Sep 17 00:00:00 2001 From: Tim Purdum Date: Tue, 19 May 2026 18:04:29 -0400 Subject: [PATCH 4/5] Key sample-page metadata to URI to fix first-nav rendering The "About this sample" details block, per-page meta tags, and JSON-LD SoftwareSourceCode entry were missing on the first navigation from the navbar - they only appeared after a page refresh. The cause was a render-order race in MainLayout: the LocationChanged handler cleared LayoutService.CurrentPage, but on first navigation the layout could re-render with the new URL before the new SamplePage's OnInitialized had a chance to re-register itself. Replace the clear-on-navigation approach with a URI key on LayoutService - SamplePage records the URI it set CurrentPage for, and MainLayout's new EffectiveCurrentPage getter only treats CurrentPage as live when that URI matches NavigationManager.Uri. Stale references after navigating to a non-SamplePage route are silently ignored with no timing dependency. While there, enrich the per-page JSON-LD with keywords and mainEntity/mainEntityOfPage cross-references so each sample page emits visibly distinct schema.org content, and fix the unresolved double scrollbar on narrow screens by moving article.content's fixed height and overflow-y into the >=1075px media query (where
is set to overflow:hidden). --- .../Shared/LayoutService.cs | 21 ++-- .../Shared/MainLayout.razor | 103 ++++++++++++------ .../Shared/MainLayout.razor.css | 8 +- .../Shared/SamplePage.cs | 7 +- 4 files changed, 92 insertions(+), 47 deletions(-) diff --git a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/LayoutService.cs b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/LayoutService.cs index 9bf823e..16e9f66 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/LayoutService.cs +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/LayoutService.cs @@ -1,21 +1,22 @@ namespace dymaptic.GeoBlazor.Core.Sample.Shared.Shared; -// LayoutStateService.cs public class LayoutService { public SamplePage? CurrentPage { get; private set; } + + // URI the CurrentPage was registered for. Consumers should only treat + // CurrentPage as live when this matches the layout's current URI — + // that way stale references from a previously-rendered SamplePage are + // silently ignored after navigation, with no race against component + // initialization order. + public string? PageUri { get; private set; } + public event Action? OnPageChanged; - public void SetCurrentPage(SamplePage page) + public void SetCurrentPage(SamplePage page, string uri) { CurrentPage = page; + PageUri = uri; OnPageChanged?.Invoke(); } - - public void ClearCurrentPage() - { - if (CurrentPage is null) return; - CurrentPage = null; - OnPageChanged?.Invoke(); - } -} \ No newline at end of file +} 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 5fe5762..2c0188c 100644 --- a/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor +++ b/samples/core/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/MainLayout.razor @@ -1,4 +1,4 @@ -@inherits LayoutComponentBase +@inherits LayoutComponentBase @implements IDisposable GeoBlazor Samples @@ -23,13 +23,13 @@