Fix release API proxy routes + wire pipeline to real data
- Add nginx proxy blocks for /api/v1/release-orchestrator/, /api/v1/release-control/, /api/v2/releases/, /api/v1/releases/, /api/v1/registries/ in Dockerfile.console - All release UI calls now reach JobEngine (401 not 404) - Registry search reaches Scanner service - Pipeline page uses ReleaseManagementStore (real API, no mock data) - Deployment wizard uses BundleOrganizerApi for create/seal - Inline version/hotfix creation in deployment wizard wired to API - Version detail shows "not found" error instead of blank screen - Version wizard has promotion lane + duplicate component detection - Sprint plan for 41 missing backend endpoints created Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -211,9 +211,11 @@ internal static class ElkEdgeChannels
|
||||
if (sinkBandsByEdgeId.ContainsKey(sorted[index].Id))
|
||||
{
|
||||
var sourceNode = positionedNodes[sorted[index].SourceNodeId];
|
||||
var isGatewaySource = string.Equals(sourceNode.Kind, "Decision", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(sourceNode.Kind, "Fork", StringComparison.OrdinalIgnoreCase);
|
||||
if (isGatewaySource)
|
||||
var hasOtherForwardEdge = sorted.Length > 1
|
||||
|| forwardEdgesBySource.TryGetValue(sorted[index].SourceNodeId, out var allSourceEdges)
|
||||
&& allSourceEdges.Any(e => !sinkBandsByEdgeId.ContainsKey(e.Id));
|
||||
var isNonChainSource = !string.Equals(sourceNode.Kind, "Task", StringComparison.OrdinalIgnoreCase);
|
||||
if (hasOtherForwardEdge && isNonChainSource)
|
||||
{
|
||||
sinkBand = (-1, 0, 0d, double.NaN);
|
||||
}
|
||||
|
||||
@@ -80,10 +80,44 @@ internal static class ElkEdgeRouter
|
||||
targetPoint = new ElkPoint { X = adjustedX, Y = targetNode.Y };
|
||||
}
|
||||
|
||||
string? multiSideOverride = null;
|
||||
if (string.IsNullOrWhiteSpace(edge.TargetPortId)
|
||||
&& direction == ElkLayoutDirection.LeftToRight
|
||||
&& (string.Equals(targetNode.Kind, "End", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(targetNode.Kind, "Join", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
var sourceCenterY = sourceNode.Y + (sourceNode.Height / 2d);
|
||||
var targetCenterY = targetNode.Y + (targetNode.Height / 2d);
|
||||
var verticalOffset = sourceCenterY - targetCenterY;
|
||||
var threshold = targetNode.Height * 0.4d;
|
||||
if (verticalOffset < -threshold)
|
||||
{
|
||||
targetPoint = new ElkPoint { X = targetNode.X + (targetNode.Width / 2d), Y = targetNode.Y };
|
||||
multiSideOverride = "NORTH";
|
||||
}
|
||||
else if (verticalOffset > threshold)
|
||||
{
|
||||
targetPoint = new ElkPoint { X = targetNode.X + (targetNode.Width / 2d), Y = targetNode.Y + targetNode.Height };
|
||||
multiSideOverride = "SOUTH";
|
||||
}
|
||||
}
|
||||
|
||||
var bendPoints = direction == ElkLayoutDirection.LeftToRight
|
||||
? ElkEdgeRouterBendPoints.BuildHorizontalBendPoints(sourceNode, targetNode, sourcePoint, targetPoint, graphBounds, channel, layerBoundariesByNodeId)
|
||||
: ElkEdgeRouterBendPoints.BuildVerticalBendPoints(sourceNode, targetNode, sourcePoint, targetPoint, graphBounds, channel, layerBoundariesByNodeId);
|
||||
|
||||
if (multiSideOverride is not null)
|
||||
{
|
||||
var approachList = bendPoints is List<ElkPoint> list ? list : new List<ElkPoint>(bendPoints);
|
||||
var approachOffset = 24d;
|
||||
var approachX = targetNode.X + (targetNode.Width / 2d);
|
||||
var approachY = multiSideOverride == "NORTH"
|
||||
? targetNode.Y - approachOffset
|
||||
: targetNode.Y + targetNode.Height + approachOffset;
|
||||
approachList.Add(new ElkPoint { X = approachX, Y = approachY });
|
||||
bendPoints = approachList;
|
||||
}
|
||||
|
||||
var routedKind = channel.RouteMode == EdgeRouteMode.BackwardOuter
|
||||
? $"backward|usc={channel.UseSourceCollector}|sox={channel.SharedOuterX:F0}"
|
||||
: edge.Kind;
|
||||
@@ -192,10 +226,17 @@ internal static class ElkEdgeRouter
|
||||
{
|
||||
if (positionedNodes.TryGetValue(dummyId, out var dummyPos))
|
||||
{
|
||||
var centerY = dummyPos.Y + (dummyPos.Height / 2d);
|
||||
if (channel.RouteMode == EdgeRouteMode.Direct
|
||||
&& (centerY > graphBounds.MaxY + 8d || centerY < graphBounds.MinY - 8d))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bendPoints.Add(new ElkPoint
|
||||
{
|
||||
X = dummyPos.X + (dummyPos.Width / 2d),
|
||||
Y = dummyPos.Y + (dummyPos.Height / 2d),
|
||||
Y = centerY,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -213,6 +254,32 @@ internal static class ElkEdgeRouter
|
||||
var targetAnchor = ElkEdgeRouterAnchors.ComputeSmartAnchor(targetNode, bendPoints.Count > 0 ? bendPoints[^1] : null,
|
||||
false, targetEntryY, targetGroup?.Length ?? 1, direction);
|
||||
|
||||
if (direction == ElkLayoutDirection.LeftToRight
|
||||
&& (string.Equals(targetNode.Kind, "End", StringComparison.OrdinalIgnoreCase)
|
||||
|| string.Equals(targetNode.Kind, "Join", StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
var sourceCenterY = sourceNode.Y + (sourceNode.Height / 2d);
|
||||
var targetCenterY = targetNode.Y + (targetNode.Height / 2d);
|
||||
var verticalOffset = sourceCenterY - targetCenterY;
|
||||
var sideThreshold = targetNode.Height * 0.4d;
|
||||
if (verticalOffset < -sideThreshold)
|
||||
{
|
||||
targetAnchor = ElkEdgeRouterAnchors.ResolvePreferredAnchorPoint(
|
||||
targetNode, sourceNode.X + sourceNode.Width, targetNode.Y - 256d, "NORTH", direction);
|
||||
var approachOffset = 24d;
|
||||
var approachX = targetNode.X + (targetNode.Width / 2d);
|
||||
bendPoints.Add(new ElkPoint { X = approachX, Y = targetNode.Y - approachOffset });
|
||||
}
|
||||
else if (verticalOffset > sideThreshold)
|
||||
{
|
||||
targetAnchor = ElkEdgeRouterAnchors.ResolvePreferredAnchorPoint(
|
||||
targetNode, sourceNode.X + sourceNode.Width, targetNode.Y + targetNode.Height + 256d, "SOUTH", direction);
|
||||
var approachOffset = 24d;
|
||||
var approachX = targetNode.X + (targetNode.Width / 2d);
|
||||
bendPoints.Add(new ElkPoint { X = approachX, Y = targetNode.Y + targetNode.Height + approachOffset });
|
||||
}
|
||||
}
|
||||
|
||||
reconstructed[edge.Id] = new ElkRoutedEdge
|
||||
{
|
||||
Id = edge.Id,
|
||||
|
||||
@@ -222,8 +222,8 @@ internal static class ElkEdgeRouterBendPoints
|
||||
var targetApproachX = Math.Max(sourceExitX + 24d, targetBoundary.MinX - 32d);
|
||||
var outerY = graphBounds.MaxY + 32d + ElkEdgeChannelBands.ResolveSinkBandOffset(Math.Max(0, channel.SinkBandIndex));
|
||||
|
||||
var horizontalSpan = targetApproachX - sourceExitX;
|
||||
if (horizontalSpan > 200d)
|
||||
var corridorSpan = targetApproachX - sourceExitX;
|
||||
if (corridorSpan > 200d)
|
||||
{
|
||||
return ElkLayoutHelpers.NormalizeBendPoints(
|
||||
new ElkPoint { X = targetApproachX, Y = startPoint.Y },
|
||||
@@ -256,8 +256,8 @@ internal static class ElkEdgeRouterBendPoints
|
||||
? graphBounds.MinY - 56d - ElkEdgeChannelBands.ResolveSinkBandOffset(Math.Max(0, channel.SinkBandIndex), 36d, 28d)
|
||||
: channel.PreferredOuterY + ElkEdgeChannelBands.ResolveSinkBandOffset(Math.Max(0, channel.SinkBandIndex), 28d, 24d);
|
||||
|
||||
var topHorizontalSpan = targetApproachX - sourceExitX;
|
||||
if (topHorizontalSpan > 200d)
|
||||
var topCorridorSpan = targetApproachX - sourceExitX;
|
||||
if (topCorridorSpan > 200d)
|
||||
{
|
||||
return ElkLayoutHelpers.NormalizeBendPoints(
|
||||
new ElkPoint { X = targetApproachX, Y = startPoint.Y },
|
||||
|
||||
24
src/__Libraries/StellaOps.ElkSharp/StellaOps.ElkSharp.sln
Normal file
24
src/__Libraries/StellaOps.ElkSharp/StellaOps.ElkSharp.sln
Normal file
@@ -0,0 +1,24 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.5.2.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StellaOps.ElkSharp", "StellaOps.ElkSharp.csproj", "{C14F76B1-AFCA-BAF5-D682-EFA322DF1D6E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{C14F76B1-AFCA-BAF5-D682-EFA322DF1D6E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C14F76B1-AFCA-BAF5-D682-EFA322DF1D6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C14F76B1-AFCA-BAF5-D682-EFA322DF1D6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C14F76B1-AFCA-BAF5-D682-EFA322DF1D6E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {4342DA81-8C0D-4763-BDF9-77353C422BA9}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Reference in New Issue
Block a user