diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/About.razor b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/About.razor index fb4f0187..90f45bc5 100644 --- a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/About.razor +++ b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/About.razor @@ -31,9 +31,7 @@

Need help creating your own Geospatial Information System, maps, or data applications?

Visit dymaptic.com or email us and let us know how we can help you!

- - - Follow @@GeoBlazor - +
+ Go Pro with the GeoBlazor Pro package! +
\ No newline at end of file diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/About.razor.css b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/About.razor.css index e677fd26..357f8beb 100644 --- a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/About.razor.css +++ b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/About.razor.css @@ -49,6 +49,16 @@ font: normal normal normal 12px/18px 'Helvetica Neue', Arial, sans-serif; } +.pro { + color: gold; + font-style: italic; + font-weight: bold; + padding: 1rem 0; +} + +.pro a { + color: gold!important; +} @media (max-width: 799px) { #feature-inset { diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ClickToAdd.razor b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ClickToAdd.razor new file mode 100644 index 00000000..aed1a17c --- /dev/null +++ b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Pages/ClickToAdd.razor @@ -0,0 +1,64 @@ +@page "/click-to-add" +Click to Add Points +

Click To Add Points

+ + +

+ Click anywhere to see a point added to the map. Click on the point again to see a popup. Click on the popup action to add the point to the list below. +

+ + + + + + + + + + + + +
+

Points Clicked

+ @foreach (Point point in _points) + { +

Long: @point.Longitude!.Value.ToString("N2") Lat: @point.Latitude!.Value.ToString("N2")

+ } +
+ +@code { + private async Task OnClick(ClickEvent arg) + { + Point point = arg.MapPoint; + if (_graphic is null) + { + _graphic = new Graphic(point); + await _graphicsLayer!.Add(_graphic); + } + + SimpleMarkerSymbol symbol = new SimpleMarkerSymbol(new Outline(new MapColor("blue")), + new MapColor("yellow"), 10); + + ActionButton actionButton = new ActionButton("Click to Add to List", + "./_content/dymaptic.GeoBlazor.Core.Sample.Shared/images/dymaptic_logo.png", "test-1", AddPoint); + PopupTemplate popupTemplate = new PopupTemplate( + $"New Point at Long: {point.Longitude!.Value:N2} Lat: {point.Latitude!.Value:N2}", + actions: new[]{ actionButton }); + + await _graphic.SetPopupTemplate(popupTemplate); + await _graphic.SetSymbol(symbol); + await _graphic.SetGeometry(point); + } + + private async Task AddPoint() + { + _points.Add(((Point)_graphic!.Geometry!).Clone()); + await InvokeAsync(StateHasChanged); + } + + private Graphic? _graphic; + private GraphicsLayer? _graphicsLayer; + private readonly List _points = new(); +} \ No newline at end of file diff --git a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/NavMenu.razor b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/NavMenu.razor index 8e28c18a..c3c9dab2 100644 --- a/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/NavMenu.razor +++ b/samples/dymaptic.GeoBlazor.Core.Sample.Shared/Shared/NavMenu.razor @@ -71,6 +71,7 @@ new("", "Home", "oi-home"), new("navigation", "Navigation", "oi-compass"), new("drawing", "Drawing", "oi-pencil"), + new("click-to-add", "Click to Add Point", "oi-map-marker"), new("many-graphics", "Many Graphics", "oi-calculator"), new("scene", "Scene & Attributes", "oi-globe"), new("widgets", "Widgets", "oi-location"), diff --git a/src/dymaptic.GeoBlazor.Core/Components/ActionBase.cs b/src/dymaptic.GeoBlazor.Core/Components/ActionBase.cs index f726d274..45afd904 100644 --- a/src/dymaptic.GeoBlazor.Core/Components/ActionBase.cs +++ b/src/dymaptic.GeoBlazor.Core/Components/ActionBase.cs @@ -108,6 +108,56 @@ internal record ActionBaseSerializationRecord([property: JsonIgnore(Condition = /// public class ActionButton : ActionBase { + /// + /// Parameterless constructor for use as a razor component. + /// + public ActionButton() + { + } + + /// + /// Constructor for use in code. + /// + /// + /// The title of the action. + /// + /// + /// The URL to an image that will be used to represent the action. This property will be used as a background image + /// + /// + /// The name of the ID assigned to this action. + /// + /// + /// The action function to perform on click. + /// + /// + /// This adds a CSS class to the ActionButton's node. + /// + /// + /// Set this property to true to display a spinner icon. + /// + /// + /// Indicates whether this action is disabled. + /// + /// + /// Indicates if the action is visible. + /// + public ActionButton(string? title = null, string? image = null, string? id = null, + Func? callbackFunction = null, string? className = null, bool? active = null, bool? disabled = null, + bool? visible = null) + { +#pragma warning disable BL0005 + Title = title; + Image = image; + Id = id; + CallbackFunction = callbackFunction; + ClassName = className; + Active = active; + Disabled = disabled; + Visible = visible; +#pragma warning restore BL0005 + } + /// public override string Type => "button"; @@ -141,6 +191,51 @@ internal override ActionBaseSerializationRecord ToSerializationRecord() /// public class ActionToggle : ActionBase { + /// + /// Parameterless constructor for use as a razor component. + /// + public ActionToggle() + { + } + + /// + /// Constructor for use in code. + /// + /// + /// The title of the action. + /// + /// + /// The name of the ID assigned to this action. + /// + /// + /// The action function to perform on click. + /// + /// + /// Indicates the value of whether the action is toggled on/off. + /// + /// + /// Set this property to true to display a spinner icon. + /// + /// + /// Indicates whether this action is disabled. + /// + /// + /// Indicates if the action is visible. + /// + public ActionToggle(string? title = null, string? id = null, Func? callbackFunction = null, + bool? value = null, bool? active = null, bool? disabled = null, bool? visible = null) + { +#pragma warning disable BL0005 + Title = title; + Id = id; + CallbackFunction = callbackFunction; + Value = value; + Active = active; + Disabled = disabled; + Visible = visible; +#pragma warning restore BL0005 + } + /// public override string Type => "toggle"; diff --git a/src/dymaptic.GeoBlazor.Core/Components/Popups/PopupTemplate.cs b/src/dymaptic.GeoBlazor.Core/Components/Popups/PopupTemplate.cs index eaa15484..cca30964 100644 --- a/src/dymaptic.GeoBlazor.Core/Components/Popups/PopupTemplate.cs +++ b/src/dymaptic.GeoBlazor.Core/Components/Popups/PopupTemplate.cs @@ -331,7 +331,7 @@ internal PopupTemplateSerializationRecord ToSerializationRecord() FieldInfos?.Select(f => f.ToSerializationRecord()), Content.Select(c => c.ToSerializationRecord()), ExpressionInfos?.Select(e => e.ToSerializationRecord()), OverwriteActions, - ReturnGeometry, Actions?.Select(a => a.ToSerializationRecord())); + ReturnGeometry, Actions?.Select(a => a.ToSerializationRecord()), Id.ToString()); } } @@ -362,5 +362,8 @@ internal record PopupTemplateSerializationRecord([property: JsonIgnore(Condition bool? ReturnGeometry = null, [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] [property: ProtoMember(9)] - IEnumerable? Actions = null) + IEnumerable? Actions = null, + [property: JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)] + [property: ProtoMember(10)] + string? id = null) : MapComponentSerializationRecord; \ No newline at end of file diff --git a/src/dymaptic.GeoBlazor.Core/Components/Views/MapView.razor.cs b/src/dymaptic.GeoBlazor.Core/Components/Views/MapView.razor.cs index e0cca48f..b136a9d0 100644 --- a/src/dymaptic.GeoBlazor.Core/Components/Views/MapView.razor.cs +++ b/src/dymaptic.GeoBlazor.Core/Components/Views/MapView.razor.cs @@ -969,6 +969,51 @@ public async Task OnJavascriptLayerViewCreateError(LayerViewCreateErrorEvent err /// [Parameter] public int? GraphicSerializationChunkSize { get; set; } + + /// + /// For internal use only, this looks up a missing for a + /// and returns it to JavaScript. + /// + [JSInvokable] + public DotNetObjectReference? GetDotNetPopupTemplateObjectReference(Guid popupTemplateId) + { + foreach (Graphic graphic in Graphics) + { + if (graphic.PopupTemplate?.Id == popupTemplateId) + { + return graphic.PopupTemplate.DotNetPopupTemplateReference; + } + } + + foreach (Layer layer in Map!.Layers) + { + switch (layer) + { + case FeatureLayer { Source: not null } featureLayer: + foreach (Graphic graphic in featureLayer.Source) + { + if (graphic.PopupTemplate?.Id == popupTemplateId) + { + return graphic.PopupTemplate.DotNetPopupTemplateReference; + } + } + + break; + case GraphicsLayer graphicsLayer: + foreach (Graphic graphic in graphicsLayer.Graphics) + { + if (graphic.PopupTemplate?.Id == popupTemplateId) + { + return graphic.PopupTemplate.DotNetPopupTemplateReference; + } + } + + break; + } + } + + return null; + } #endregion diff --git a/src/dymaptic.GeoBlazor.Core/Scripts/definitions.d.ts b/src/dymaptic.GeoBlazor.Core/Scripts/definitions.d.ts index fdf79120..1e256c6a 100644 --- a/src/dymaptic.GeoBlazor.Core/Scripts/definitions.d.ts +++ b/src/dymaptic.GeoBlazor.Core/Scripts/definitions.d.ts @@ -339,6 +339,7 @@ export interface DotNetPopupTemplate { overwriteActions: boolean; returnGeometry: boolean; dotNetPopupTemplateReference: any; + id: string; actions: any[]; } diff --git a/src/dymaptic.GeoBlazor.Core/Scripts/jsBuilder.ts b/src/dymaptic.GeoBlazor.Core/Scripts/jsBuilder.ts index d462d005..45874732 100644 --- a/src/dymaptic.GeoBlazor.Core/Scripts/jsBuilder.ts +++ b/src/dymaptic.GeoBlazor.Core/Scripts/jsBuilder.ts @@ -2,7 +2,7 @@ import Extent from "@arcgis/core/geometry/Extent"; import Graphic from "@arcgis/core/Graphic"; import PopupTemplate from "@arcgis/core/PopupTemplate"; -import { arcGisObjectRefs, triggerActionHandler } from "./arcGisJsInterop"; +import {arcGisObjectRefs, dotNetRefs, triggerActionHandler} from "./arcGisJsInterop"; import Geometry from "@arcgis/core/geometry/Geometry"; import Point from "@arcgis/core/geometry/Point"; import Polyline from "@arcgis/core/geometry/Polyline"; @@ -227,6 +227,7 @@ export function buildJsPopupTemplate(popupTemplateObject: DotNetPopupTemplate, v } else { content = async (featureSelection) => { try { + await lookupDotNetRefForPopupTemplate(popupTemplateObject, viewId as string); let results: DotNetPopupContent[] | null = await popupTemplateObject.dotNetPopupTemplateReference .invokeMethodAsync("OnContentFunction", buildDotNetGraphic(featureSelection.graphic)); return results?.map(r => buildJsPopupContent(r)); @@ -272,11 +273,13 @@ export function buildJsPopupTemplate(popupTemplateObject: DotNetPopupTemplate, v reactiveUtils.once(() => view.popup.on !== undefined) .then(() => { templateTriggerActionHandler = view.popup.on("trigger-action", async (event: PopupTriggerActionEvent) => { + await lookupDotNetRefForPopupTemplate(popupTemplateObject, viewId as string); await popupTemplateObject.dotNetPopupTemplateReference.invokeMethodAsync("OnTriggerAction", event.action.id); }); }) } else { templateTriggerActionHandler = view.popup.on("trigger-action", async (event: PopupTriggerActionEvent) => { + await lookupDotNetRefForPopupTemplate(popupTemplateObject, viewId as string); await popupTemplateObject.dotNetPopupTemplateReference.invokeMethodAsync("OnTriggerAction", event.action.id); }); } @@ -290,6 +293,14 @@ export function buildJsPopupTemplate(popupTemplateObject: DotNetPopupTemplate, v return template; } +async function lookupDotNetRefForPopupTemplate(popupTemplateObject: DotNetPopupTemplate, viewId: string) { + if (!hasValue(popupTemplateObject.dotNetPopupTemplateReference)) { + let viewRef = dotNetRefs[viewId]; + popupTemplateObject.dotNetPopupTemplateReference = + await viewRef.invokeMethodAsync('GetDotNetPopupTemplateObjectReference', popupTemplateObject.id); + } +} + export let templateTriggerActionHandler: IHandle; export function buildJsPopupContent(popupContentObject: DotNetPopupContent): ContentProperties | null { diff --git a/src/dymaptic.GeoBlazor.Core/docCopy.ps1 b/src/dymaptic.GeoBlazor.Core/docCopy.ps1 deleted file mode 100644 index e6f39969..00000000 --- a/src/dymaptic.GeoBlazor.Core/docCopy.ps1 +++ /dev/null @@ -1,19 +0,0 @@ -$FrontMatter = "---`nlayout: default`ntitle: " -$Parent = "`nparent: " -$Index = "Index`nnav_order: 1" -$EndMatter = "`n---`n" -$SourcePath = ".\Documentation" -$OutPath = "..\..\docs\pages\classes" - -Get-ChildItem -Path $OutPath -Include *.* -Exclude 'classes.md' -File -Recurse | foreach { $_.Delete() } -Write-Output "Copying Docs Files" -Get-ChildItem -Path $SourcePath -Filter "*.md" | - ForEach { - $NameComponents = ($_.BaseName -split '\.'); - $Title = $NameComponents[-1]; - $Folder = $NameComponents[-2]; - Write-Output "- $_.BaseName" - "$( $FrontMatter )$( $_.BaseName -eq 'index' ? $Index : $Title )$( $Parent )Classes$( $EndMatter )$( Get-Content $_.FullName -raw )" -replace '.md', '.html' -replace '>[\s]*ArcGIS[\s]*JS[\s]*API[\s]*', '>ArcGIS JS API' | - Out-File $_.FullName -Encoding utf8NoBOM; - Copy-Item -Path $_.FullName -Destination "$( $OutPath )" -Force - } \ No newline at end of file diff --git a/src/dymaptic.GeoBlazor.Core/dymaptic.GeoBlazor.Core.csproj b/src/dymaptic.GeoBlazor.Core/dymaptic.GeoBlazor.Core.csproj index 92c8f81e..d4a204fe 100644 --- a/src/dymaptic.GeoBlazor.Core/dymaptic.GeoBlazor.Core.csproj +++ b/src/dymaptic.GeoBlazor.Core/dymaptic.GeoBlazor.Core.csproj @@ -9,8 +9,8 @@ GeoBlazor MIT - 2.3.0 - 2.3.0 + 2.3.2 + 2.3.2 Tim Purdum, Christopher Moravec, Mara Stoica, Tim Rawson dymaptic ©2023 by dymaptic @@ -100,11 +100,6 @@ - - - - - diff --git a/src/dymaptic.GeoBlazor.Core/package-lock.json b/src/dymaptic.GeoBlazor.Core/package-lock.json index 1d5ce717..eb913e1c 100644 --- a/src/dymaptic.GeoBlazor.Core/package-lock.json +++ b/src/dymaptic.GeoBlazor.Core/package-lock.json @@ -1,12 +1,12 @@ { "name": "dymaptic.GeoBlazor.Core", - "version": "2.3.0", + "version": "2.3.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "dymaptic.GeoBlazor.Core", - "version": "2.3.0", + "version": "2.3.2", "license": "ISC", "dependencies": { "@arcgis/core": "^4.27.6", diff --git a/src/dymaptic.GeoBlazor.Core/package.json b/src/dymaptic.GeoBlazor.Core/package.json index 2d8925a4..9a766514 100644 --- a/src/dymaptic.GeoBlazor.Core/package.json +++ b/src/dymaptic.GeoBlazor.Core/package.json @@ -1,6 +1,6 @@ { "name": "dymaptic.GeoBlazor.Core", - "version": "2.3.0", + "version": "2.3.2", "description": "https://www.geoblazor.com", "main": "arcGisInterop.js", "scripts": { diff --git a/src/dymaptic.GeoBlazor.Core/wwwroot/graphic.json b/src/dymaptic.GeoBlazor.Core/wwwroot/graphic.json index 4f1da72a..14584052 100644 --- a/src/dymaptic.GeoBlazor.Core/wwwroot/graphic.json +++ b/src/dymaptic.GeoBlazor.Core/wwwroot/graphic.json @@ -309,6 +309,10 @@ "rule": "repeated", "type": "Action", "id": 9 + }, + "id": { + "type": "string", + "id": 10 } } },