Skip to content
This repository was archived by the owner on May 12, 2026. It is now read-only.

Commit 77cc5f3

Browse files
Remove 'area=yes' when selecting a preset that implies an area already
1 parent 72bfdb6 commit 77cc5f3

16 files changed

Lines changed: 182 additions & 40 deletions

File tree

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using Alidade.Osm.Models.Tagging;
2+
3+
namespace Alidade.Osm.Handlers.Tagging;
4+
5+
/// <inheritdoc />
6+
public sealed class MergePresetTags
7+
: IRequestHandler<MergePresetTags.Query, QueryResult<Dictionary<string, string>>>
8+
{
9+
/// <summary>
10+
/// Merges a preset's tags over an existing tag dictionary and removes
11+
/// <c>area=yes</c> when it is redundant because an area-implying key
12+
/// (e.g. <c>landuse</c>, <c>building</c>, <c>natural</c>) is already
13+
/// present in the merged result.
14+
/// </summary>
15+
/// <param name="CurrentTags">The element's current tags, used as the merge base.</param>
16+
/// <param name="Preset">The preset whose tags are applied on top.</param>
17+
public record Query( IReadOnlyDictionary<string, string> CurrentTags, Preset Preset)
18+
: IRequest<QueryResult<Dictionary<string, string>>>;
19+
20+
/// <inheritdoc />
21+
public Task<QueryResult<Dictionary<string, string>>> Handle( Query request, CancellationToken cancellationToken)
22+
{
23+
Dictionary<string, string> merged = new(request.CurrentTags);
24+
foreach ((string k, string v) in request.Preset.Tags)
25+
{
26+
if (v != "*")
27+
{
28+
merged[k] = v;
29+
}
30+
}
31+
32+
if (merged.TryGetValue("area", out string? areaVal)
33+
&& areaVal == "yes"
34+
&& merged.Keys.Any(OsmWay.AreaImplyingKeys.Contains))
35+
{
36+
merged.Remove("area");
37+
}
38+
39+
return Task.FromResult<QueryResult<Dictionary<string, string>>>(merged);
40+
}
41+
}

Alidade.Osm/Models/OsmWay.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public sealed record OsmWay(
4343
public bool IsClosed => NodeIds.Count >= 2 && NodeIds[0] == NodeIds[^1];
4444

4545
// Tag keys that make a closed way implicitly an area even without area=yes.
46-
private static readonly HashSet<string> AreaImplyingKeys =
46+
internal static readonly HashSet<string> AreaImplyingKeys =
4747
[
4848
"building", "building:part", "landuse", "leisure", "natural",
4949
"amenity", "shop", "place", "man_made", "military", "aeroway",

Alidade/Components/Dialogs/ConflictResolutionDialog.razor.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using Alidade.Osm.Handlers.Editing;
2+
13
namespace Alidade.Components.Dialogs;
24

35
/// <summary>

Alidade/Components/Dialogs/GridifyDialog.razor.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using System.Text.Json;
2+
using Alidade.Handlers.Map;
3+
using Alidade.Handlers.Selection;
24
using Alidade.Map.Handlers;
5+
using Alidade.Osm.Handlers.Editing;
36
using Microsoft.AspNetCore.Components;
47
using Microsoft.JSInterop;
58
using NetTopologySuite.Features;
@@ -10,7 +13,7 @@ namespace Alidade.Components.Dialogs;
1013
/// <summary>
1114
/// Floating, draggable panel for splitting a selected closed way into a grid of equal
1215
/// rectangular sub-areas. Shows a live orange dashed preview overlay while open.
13-
/// Follows the same always-in-DOM, CSS-visibility pattern as <see cref="Alidade.Components.Panels.InspectorPanel"/>.
16+
/// Follows the same always-in-DOM, CSS-visibility pattern as <see cref="Panels.InspectorPanel"/>.
1417
/// </summary>
1518
public partial class GridifyDialog(
1619
IMediator mediator,
@@ -153,7 +156,7 @@ private async Task PushPreviewAsync()
153156
return;
154157
}
155158

156-
FeatureCollection fc = new();
159+
FeatureCollection fc = [];
157160

158161
foreach (IReadOnlyList<GridifyNodeRef> cellRefs in result.CellNodeRefs)
159162
{
@@ -190,7 +193,7 @@ private async Task PushPreviewAsync()
190193

191194
private async Task ClearPreviewAsync()
192195
{
193-
FeatureCollection empty = new();
196+
FeatureCollection empty = [];
194197
string json = JsonSerializer.Serialize(empty, geoJsonOptions);
195198
await mediator.Send(new SetSourceData.Command("osm-gridify-preview", json));
196199
}
@@ -204,14 +207,14 @@ private async Task ApplyAsync()
204207

205208
await ClearPreviewAsync();
206209
await mediator.Send(new GridifyWay.Command(_wayId.Value, _rows, _cols, _rotation));
207-
await mediator.Send(new Handlers.Map.ToggleGridifyDialog.Command());
208-
await mediator.Send(new Handlers.Selection.ClearSelection.Command());
210+
await mediator.Send(new ToggleGridifyDialog.Command());
211+
await mediator.Send(new ClearSelection.Command());
209212
}
210213

211214
private void Cancel()
212215
{
213216
_ = ClearPreviewAsync();
214-
_ = mediator.Send(new Handlers.Map.ToggleGridifyDialog.Command());
217+
_ = mediator.Send(new ToggleGridifyDialog.Command());
215218
}
216219

217220
/// <inheritdoc />

Alidade/Components/Panels/InspectorPanel.razor.cs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
using Alidade.Osm.Models.Nsi;
44
using Alidade.Osm.Models.Tagging;
55
using Microsoft.AspNetCore.Components.Web;
6+
using Alidade.Handlers.Map;
7+
using Alidade.Handlers.Selection;
8+
using Alidade.Osm.Handlers.Editing;
9+
using Alidade.Osm.Handlers.Tagging;
610

711
namespace Alidade.Components.Panels;
812

@@ -22,7 +26,8 @@ public partial class InspectorPanel(
2226
/// <summary>
2327
/// When set, the panel is pinned to this element and does not follow selection changes.
2428
/// </summary>
25-
[Parameter] public OsmElementRef? PinnedRef { get; set; }
29+
[Parameter]
30+
public OsmElementRef? PinnedRef { get; set; }
2631

2732
private bool IsPinned => PinnedRef is not null;
2833

@@ -259,9 +264,12 @@ OsmElementTypes.Relation when buf.Relations.TryGetValue(_targetRef.Id, out OsmRe
259264
RefreshPreset();
260265
}
261266

262-
private void ApplyPreset(Preset preset)
267+
private async Task ApplyPreset(Preset preset)
263268
{
264-
if (_targetRef is null) return;
269+
if (_targetRef is null)
270+
{
271+
return;
272+
}
265273

266274
EditBufferState buf = editBufferState.State;
267275
IReadOnlyDictionary<string, string>? currentTags = _targetRef.Type switch
@@ -272,15 +280,18 @@ OsmElementTypes.Relation when buf.Relations.TryGetValue(_targetRef.Id, out OsmRe
272280
_ => null
273281
};
274282

275-
if (currentTags is null) return;
283+
if (currentTags is null)
284+
{
285+
return;
286+
}
276287

277-
Dictionary<string, string> merged = new(currentTags);
278-
foreach ((string k, string v) in preset.Tags)
288+
Dictionary<string, string>? merged = await mediator.Send(new MergePresetTags.Query(currentTags, preset));
289+
if (merged is null)
279290
{
280-
if (v != "*") merged[k] = v;
291+
return;
281292
}
282293

283-
_ = mediator.Send(new UpdateTags.Command(_targetRef, currentTags, merged));
294+
await mediator.Send(new UpdateTags.Command(_targetRef, currentTags, merged));
284295
_activePreset = preset;
285296
_query = string.Empty;
286297
_isSearching = false;
@@ -292,19 +303,19 @@ private void PinCurrent()
292303
{
293304
if (_targetRef is not null)
294305
{
295-
_ = mediator.Send(new Handlers.Map.PinInspector.Command(_targetRef));
306+
_ = mediator.Send(new PinInspector.Command(_targetRef));
296307
}
297308
}
298309

299310
private void OnClose()
300311
{
301312
if (IsPinned)
302313
{
303-
_ = mediator.Send(new Handlers.Map.UnpinInspector.Command(PinnedRef!));
314+
_ = mediator.Send(new UnpinInspector.Command(PinnedRef!));
304315
}
305316
else
306317
{
307-
_ = mediator.Send(new Handlers.Selection.ClearSelection.Command());
318+
_ = mediator.Send(new ClearSelection.Command());
308319
}
309320
}
310321

Alidade/Components/Panels/PresetField.razor.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.AspNetCore.Components;
22
using Alidade.Osm.Models.Tagging;
3+
using Alidade.Osm.Handlers.Editing;
34

45
namespace Alidade.Components.Panels;
56

Alidade/Components/Panels/PresetPanel.razor.cs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
using Alidade.Osm.Handlers.Editing;
2+
using Alidade.Osm.Handlers.Tagging;
13
using Alidade.Osm.Models.Tagging;
24
using Microsoft.AspNetCore.Components;
35

@@ -106,14 +108,10 @@ OsmElementTypes.Relation when buf.Relations.TryGetValue(selected.Id, out OsmRela
106108
return;
107109
}
108110

109-
// Merge preset tags over existing tags and preserve unrelated tags
110-
Dictionary<string, string> merged = new(currentTags);
111-
foreach ((string k, string v) in preset.Tags)
111+
Dictionary<string, string>? merged = await Mediator.Send(new MergePresetTags.Query(currentTags, preset));
112+
if (merged is null)
112113
{
113-
if (v != "*")
114-
{
115-
merged[k] = v;
116-
}
114+
return;
117115
}
118116

119117
await Mediator.Send(new UpdateTags.Command(selected, currentTags, merged));

Alidade/Components/Panels/RelationsSection.razor.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Alidade.Osm.Handlers.Editing;
12
using Microsoft.AspNetCore.Components;
23

34
namespace Alidade.Components.Panels;

Alidade/Components/Panels/TagEditor.razor.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.AspNetCore.Components;
22
using Alidade.Osm.Models.Nsi;
3+
using Alidade.Osm.Handlers.Editing;
34

45
namespace Alidade.Components.Panels;
56

Alidade/GlobalUsings.cs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,34 @@
11
global using System.Collections.Immutable;
22
global using Questy;
3+
4+
global using Alidade.Handlers.EditBuffer;
5+
global using Alidade.Models;
6+
global using Alidade.Models.EditBuffer.Draft;
7+
global using Alidade.Models.Map;
8+
global using Alidade.Models.Selection;
9+
global using Alidade.Models.Tool;
10+
global using Alidade.Models.Validation;
11+
global using Alidade.PipelineBehaviors;
12+
global using Alidade.Services;
13+
global using Alidade.Services.State;
14+
315
global using Alidade.Core.Consts;
416
global using Alidade.Core.Enums;
517
global using Alidade.Core.Models.CQRS;
6-
global using Alidade.Handlers.EditBuffer;
7-
global using Alidade.Osm.Handlers.Editing;
818
global using Alidade.Core.Models.CQRS.Request;
919
global using Alidade.Core.Models.CQRS.Response;
1020
global using Alidade.Core.Models.Settings;
1121
global using Alidade.Core.ServiceInterface;
1222
global using Alidade.Core.Services;
23+
1324
global using Alidade.Map.Models;
1425
global using Alidade.Map.Notifications;
15-
global using Alidade.Models;
16-
global using Alidade.Models.EditBuffer.Draft;
17-
global using Alidade.Osm.Models.EditBuffer;
18-
global using Alidade.Models.Map;
19-
global using Alidade.Models.Selection;
20-
global using Alidade.Models.Tool;
21-
global using Alidade.Models.Validation;
22-
global using Alidade.Osm.Services;
23-
global using Alidade.Osm.Services.State;
24-
global using Alidade.Osm.Models.Api.Auth;
26+
2527
global using Alidade.Osm.Enums;
2628
global using Alidade.Osm.Models;
29+
global using Alidade.Osm.Models.Api.Auth;
30+
global using Alidade.Osm.Models.EditBuffer;
2731
global using Alidade.Osm.Models.Validation;
32+
global using Alidade.Osm.Services;
33+
global using Alidade.Osm.Services.State;
2834
global using Alidade.Osm.Validators;
29-
global using Alidade.PipelineBehaviors;
30-
global using Alidade.Services;
31-
global using Alidade.Services.State;

0 commit comments

Comments
 (0)