From 3c1f7ad289a37e80fe9e881def5cb84fb5e48b74 Mon Sep 17 00:00:00 2001
From: Jan Calanog
Date: Fri, 12 Sep 2025 11:51:18 +0200
Subject: [PATCH 1/7] Refactor applies_to
---
.../Myst/Components/ApplicabilityItem.cs | 13 +
.../Myst/Components/ApplicabilityMappings.cs | 64 ++++
.../Myst/Components/ApplicabilityRenderer.cs | 147 +++++++
.../Components/ApplicableToComponent.cshtml | 359 +-----------------
.../Myst/Components/ApplicableToViewModel.cs | 169 +++++++++
.../Applicability/ApplicableToComponent.fs | 26 ++
6 files changed, 436 insertions(+), 342 deletions(-)
create mode 100644 src/Elastic.Markdown/Myst/Components/ApplicabilityItem.cs
create mode 100644 src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
create mode 100644 src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityItem.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityItem.cs
new file mode 100644
index 000000000..d5a71f78b
--- /dev/null
+++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityItem.cs
@@ -0,0 +1,13 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using Elastic.Documentation.AppliesTo;
+
+namespace Elastic.Markdown.Myst.Components;
+
+public record ApplicabilityItem(
+ string Key,
+ Applicability Applicability,
+ ApplicabilityRenderer.ApplicabilityRenderData RenderData
+);
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
new file mode 100644
index 000000000..826d939e4
--- /dev/null
+++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
@@ -0,0 +1,64 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using Elastic.Documentation.Configuration.Versions;
+
+namespace Elastic.Markdown.Myst.Components;
+
+public static class ApplicabilityMappings
+{
+ public record ApplicabilityDefinition(string Key, string DisplayName, VersioningSystemId VersioningSystemId);
+
+ private static readonly Dictionary Mappings = new()
+ {
+ // Stack
+ ["stack"] = new ApplicabilityDefinition("Stack", "Elastic Stack", VersioningSystemId.Stack),
+
+ // Serverless
+ ["serverless"] = new ApplicabilityDefinition("Serverless", "Elastic Cloud Serverless", VersioningSystemId.Serverless),
+ ["serverless-elasticsearch"] = new ApplicabilityDefinition("Serverless Elasticsearch", "Serverless Elasticsearch projects", VersioningSystemId.ElasticsearchProject),
+ ["serverless-observability"] = new ApplicabilityDefinition("Serverless Observability", "Serverless Observability projects", VersioningSystemId.ObservabilityProject),
+ ["serverless-security"] = new ApplicabilityDefinition("Serverless Security", "Serverless Security projects", VersioningSystemId.SecurityProject),
+
+ // Deployment
+ ["ech"] = new ApplicabilityDefinition("ECH", "Elastic Cloud Hosted", VersioningSystemId.Ess),
+ ["eck"] = new ApplicabilityDefinition("ECK", "Elastic Cloud on Kubernetes", VersioningSystemId.Eck),
+ ["ece"] = new ApplicabilityDefinition("ECE", "Elastic Cloud Enterprise", VersioningSystemId.Ece),
+ ["self"] = new ApplicabilityDefinition("Self-Managed", "Self-managed Elastic deployments", VersioningSystemId.Self),
+
+ // Product Applicability
+ ["ecctl"] = new ApplicabilityDefinition("ECCTL", "Elastic Cloud Control", VersioningSystemId.Ecctl),
+ ["curator"] = new ApplicabilityDefinition("Curator", "Curator", VersioningSystemId.Curator),
+
+ // EDOT Products
+ ["edot-android"] = new ApplicabilityDefinition("EDOT Android", "Elastic Distribution of OpenTelemetry Android", VersioningSystemId.EdotAndroid),
+ ["edot-cf-aws"] = new ApplicabilityDefinition("EDOT CF AWS", "Elastic Distribution of OpenTelemetry Cloud Forwarder for AWS", VersioningSystemId.EdotCfAws),
+ ["edot-collector"] = new ApplicabilityDefinition("EDOT Collector", "Elastic Distribution of OpenTelemetry Collector", VersioningSystemId.EdotCollector),
+ ["edot-dotnet"] = new ApplicabilityDefinition("EDOT .NET", "Elastic Distribution of OpenTelemetry .NET", VersioningSystemId.EdotDotnet),
+ ["edot-ios"] = new ApplicabilityDefinition("EDOT iOS", "Elastic Distribution of OpenTelemetry iOS", VersioningSystemId.EdotIos),
+ ["edot-java"] = new ApplicabilityDefinition("EDOT Java", "Elastic Distribution of OpenTelemetry Java", VersioningSystemId.EdotJava),
+ ["edot-node"] = new ApplicabilityDefinition("EDOT Node.js", "Elastic Distribution of OpenTelemetry Node.js", VersioningSystemId.EdotNode),
+ ["edot-php"] = new ApplicabilityDefinition("EDOT PHP", "Elastic Distribution of OpenTelemetry PHP", VersioningSystemId.ApmAgentPhp),
+ ["edot-python"] = new ApplicabilityDefinition("EDOT Python", "Elastic Distribution of OpenTelemetry Python", VersioningSystemId.EdotPython),
+
+ // APM Agents
+ ["apm-agent-android"] = new ApplicabilityDefinition("APM Agent Android", "Application Performance Monitoring Agent for Android", VersioningSystemId.ApmAgentAndroid),
+ ["apm-agent-dotnet"] = new ApplicabilityDefinition("APM Agent .NET", "Application Performance Monitoring Agent for .NET", VersioningSystemId.ApmAgentDotnet),
+ ["apm-agent-go"] = new ApplicabilityDefinition("APM Agent Go", "Application Performance Monitoring Agent for Go", VersioningSystemId.ApmAgentGo),
+ ["apm-agent-ios"] = new ApplicabilityDefinition("APM Agent iOS", "Application Performance Monitoring Agent for iOS", VersioningSystemId.ApmAgentIos),
+ ["apm-agent-java"] = new ApplicabilityDefinition("APM Agent Java", "Application Performance Monitoring Agent for Java", VersioningSystemId.ApmAgentJava),
+ ["apm-agent-node"] = new ApplicabilityDefinition("APM Agent Node.js", "Application Performance Monitoring Agent for Node.js", VersioningSystemId.ApmAgentNode),
+ ["apm-agent-php"] = new ApplicabilityDefinition("APM Agent PHP", "Application Performance Monitoring Agent for PHP", VersioningSystemId.ApmAgentPhp),
+ ["apm-agent-python"] = new ApplicabilityDefinition("APM Agent Python", "Application Performance Monitoring Agent for Python", VersioningSystemId.ApmAgentPython),
+ ["apm-agent-ruby"] = new ApplicabilityDefinition("APM Agent Ruby", "Application Performance Monitoring Agent for Ruby", VersioningSystemId.ApmAgentRuby),
+ ["apm-agent-rum"] = new ApplicabilityDefinition("APM Agent RUM", "Application Performance Monitoring Agent for Real User Monitoring", VersioningSystemId.ApmAgentRum),
+
+ // Generic product
+ ["product"] = new ApplicabilityDefinition("", "", VersioningSystemId.All)
+ };
+
+ public static ApplicabilityDefinition GetProductDefinition(string productKey) => Mappings.TryGetValue(productKey, out var definition)
+ ? definition
+ : throw new ArgumentException($"Unknown product key: {productKey}");
+}
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs
new file mode 100644
index 000000000..11e22e297
--- /dev/null
+++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs
@@ -0,0 +1,147 @@
+// Licensed to Elasticsearch B.V under one or more agreements.
+// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
+// See the LICENSE file in the project root for more information
+
+using System.Diagnostics.CodeAnalysis;
+using Elastic.Documentation;
+using Elastic.Documentation.AppliesTo;
+using Elastic.Documentation.Configuration.Versions;
+
+namespace Elastic.Markdown.Myst.Components;
+
+public class ApplicabilityRenderer
+{
+ public record ApplicabilityRenderData(
+ string BadgeText,
+ string Version,
+ string TooltipText,
+ string LifecycleClass,
+ bool ShowLifecycle,
+ bool ShowVersion
+ );
+
+ public ApplicabilityRenderData RenderApplicability(
+ Applicability applicability,
+ ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition,
+ VersioningSystem versioningSystem,
+ AppliesCollection allApplications)
+ {
+ var lifecycleClass = applicability.GetLifeCycleName().ToLowerInvariant().Replace(" ", "-");
+ var lifecycleFull = GetLifecycleFullText(applicability.Lifecycle);
+ var realVersion = TryGetRealVersion(applicability, out var v) ? v : null;
+
+ var tooltipText = BuildTooltipText(applicability, applicabilityDefinition, versioningSystem, realVersion, lifecycleFull);
+ var badgeText = BuildBadgeText(applicability, applicabilityDefinition, versioningSystem, realVersion, allApplications);
+ var badgeTextChanged = badgeText != applicabilityDefinition.Key;
+
+ var showLifecycle = applicability.Lifecycle != ProductLifecycle.GenerallyAvailable && !badgeTextChanged;
+ var showVersion = applicability.Version is not null and not AllVersions;
+
+ var version = showVersion && versioningSystem.Current >= applicability.Version!
+ ? applicability.Version!.ToString()
+ : badgeText;
+
+ return new ApplicabilityRenderData(
+ BadgeText: badgeText,
+ Version: version,
+ TooltipText: tooltipText,
+ LifecycleClass: lifecycleClass,
+ ShowLifecycle: showLifecycle,
+ ShowVersion: showVersion
+ );
+ }
+
+ private static string GetLifecycleFullText(ProductLifecycle lifecycle) => lifecycle switch
+ {
+ ProductLifecycle.GenerallyAvailable => "Available",
+ ProductLifecycle.Beta => "Available in beta",
+ ProductLifecycle.TechnicalPreview => "Available in technical preview",
+ ProductLifecycle.Deprecated => "Deprecated",
+ ProductLifecycle.Removed => "Removed",
+ ProductLifecycle.Unavailable => "Not available",
+ _ => ""
+ };
+
+ private static string BuildTooltipText(
+ Applicability applicability,
+ ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition,
+ VersioningSystem versioningSystem,
+ SemVersion? realVersion,
+ string lifecycleFull)
+ {
+ var tooltipText = "";
+
+ tooltipText = realVersion is not null
+ ? realVersion <= versioningSystem.Current
+ ? $"{lifecycleFull} on {applicabilityDefinition.DisplayName} version {realVersion} and later unless otherwise specified."
+ : applicability.Lifecycle switch
+ {
+ ProductLifecycle.GenerallyAvailable
+ or ProductLifecycle.Beta
+ or ProductLifecycle.TechnicalPreview
+ or ProductLifecycle.Planned =>
+ $"We plan to add this functionality in a future {applicabilityDefinition.DisplayName} update. Subject to change.",
+ ProductLifecycle.Deprecated => $"We plan to deprecate this functionality in a future {applicabilityDefinition.DisplayName} update. Subject to change.",
+ ProductLifecycle.Removed => $"We plan to remove this functionality in a future {applicabilityDefinition.DisplayName} update. Subject to change.",
+ _ => tooltipText
+ }
+ : $"{lifecycleFull} on {applicabilityDefinition.DisplayName} unless otherwise specified.";
+
+ var disclaimer = GetDisclaimer(applicability.Lifecycle, versioningSystem.Id);
+ if (disclaimer is not null)
+ tooltipText = $"{tooltipText}\n\n{disclaimer}";
+
+ return tooltipText;
+ }
+
+ private static string? GetDisclaimer(ProductLifecycle lifecycle, VersioningSystemId versioningSystemId) => lifecycle switch
+ {
+ ProductLifecycle.Beta => "Beta features are subject to change. The design and code is less mature than official GA features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA features.",
+ ProductLifecycle.TechnicalPreview => "This functionality may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.",
+ ProductLifecycle.GenerallyAvailable => versioningSystemId is VersioningSystemId.Stack
+ ? "If this functionality is unavailable or behaves differently when deployed on ECH, ECE, ECK, or a self-managed installation, it will be indicated on the page."
+ : null,
+ _ => null
+ };
+
+ private static string BuildBadgeText(
+ Applicability applicability,
+ ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition,
+ VersioningSystem versioningSystem,
+ SemVersion? realVersion,
+ AppliesCollection allApplications)
+ {
+ var badgeText = applicabilityDefinition.Key;
+
+ if (realVersion is not null && realVersion > versioningSystem.Current)
+ {
+ badgeText = applicability.Lifecycle switch
+ {
+ ProductLifecycle.TechnicalPreview => "Planned",
+ ProductLifecycle.Beta => "Planned",
+ ProductLifecycle.GenerallyAvailable =>
+ allApplications.Any(a => a.Lifecycle is ProductLifecycle.TechnicalPreview or ProductLifecycle.Beta)
+ ? "GA planned"
+ : "Planned",
+ ProductLifecycle.Deprecated => "Deprecation planned",
+ ProductLifecycle.Removed => "Removal planned",
+ ProductLifecycle.Planned => "Planned",
+ _ => badgeText
+ };
+ }
+
+ return badgeText;
+ }
+
+ private static bool TryGetRealVersion(Applicability applicability, [NotNullWhen(true)] out SemVersion? version)
+ {
+ version = null;
+ if (applicability.Version is not null && applicability.Version != AllVersions.Instance)
+ {
+ version = applicability.Version;
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml b/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
index a8960aad9..1a0ad590d 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
+++ b/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
@@ -1,357 +1,32 @@
-@using System.Diagnostics.CodeAnalysis
-@using Elastic.Documentation
-@using Elastic.Documentation.AppliesTo
-@using Elastic.Documentation.Configuration.Versions
@inherits RazorSlice
-@{
- var appliesTo = Model.AppliesTo;
-}
-
-@if (appliesTo.Stack is not null)
-{
- @RenderProduct(
- "Stack",
- "Elastic Stack",
- VersioningSystemId.Stack,
- appliesTo.Stack
- )
-}
-@if (appliesTo.Serverless is not null)
-{
- if (appliesTo.Serverless.AllProjects is not null)
- {
- @RenderProduct(
- "Serverless",
- "Elastic Cloud Serverless",
- VersioningSystemId.Serverless,
- appliesTo.Serverless.AllProjects
- )
- }
- else
- {
- if (appliesTo.Serverless.Elasticsearch is not null)
- {
- @RenderProduct(
- "Serverless Elasticsearch",
- "Serverless Elasticsearch projects",
- VersioningSystemId.ElasticsearchProject,
- appliesTo.Serverless.Elasticsearch
- )
- }
-
- if (appliesTo.Serverless.Observability is not null)
- {
- @RenderProduct(
- "Serverless Observability",
- "Serverless Observability projects",
- VersioningSystemId.ObservabilityProject,
- appliesTo.Serverless.Observability
- )
- }
-
- if (appliesTo.Serverless.Security is not null)
- {
- @RenderProduct(
- "Serverless Security",
- "Serverless Security projects",
- VersioningSystemId.SecurityProject,
- appliesTo.Serverless.Security
- )
- }
- }
-}
-@if (appliesTo.Deployment is not null)
-{
-
- if (appliesTo.Deployment.Ess is not null)
- {
- @RenderProduct(
- "ECH",
- "Elastic Cloud Hosted",
- VersioningSystemId.Ess,
- appliesTo.Deployment.Ess
- )
- }
-
- if (appliesTo.Deployment.Eck is not null)
- {
- @RenderProduct(
- "ECK",
- "Elastic Cloud on Kubernetes",
- VersioningSystemId.Eck,
- appliesTo.Deployment.Eck
- )
- }
-
- if (appliesTo.Deployment.Ece is not null)
- {
- @RenderProduct("ECE",
- "Elastic Cloud Enterprise",
- VersioningSystemId.Ece,
- appliesTo.Deployment.Ece
- )
- }
-
- if (appliesTo.Deployment.Self is not null)
- {
- @RenderProduct(
- "Self-Managed",
- "Self-managed Elastic deployments",
- VersioningSystemId.Self,
- appliesTo.Deployment.Self
- )
- }
-}
-@if (appliesTo.ProductApplicability is not null)
-{
- var pa = appliesTo.ProductApplicability;
- if (pa.Ecctl is not null)
- {
- @RenderProduct("ECCTL", "Elastic Cloud Control", VersioningSystemId.Ecctl, pa.Ecctl)
- }
-
- if (pa.Curator is not null)
- {
- @RenderProduct("Curator", "Curator", VersioningSystemId.Curator, pa.Curator)
- }
-
- if (pa.EdotAndroid is not null)
- {
- @RenderProduct("EDOT Android", "Elastic Distribution of OpenTelemetry Android", VersioningSystemId.EdotAndroid, pa.EdotAndroid)
- }
-
- if (pa.EdotCfAws is not null)
- {
- @RenderProduct("EDOT CF AWS", "Elastic Distribution of OpenTelemetry Cloud Forwarder for AWS", VersioningSystemId.EdotCfAws, pa.EdotCfAws)
- }
-
- if (pa.EdotCollector is not null)
- {
- @RenderProduct("EDOT Collector", "Elastic Distribution of OpenTelemetry Collector", VersioningSystemId.EdotCollector, pa.EdotCollector)
- }
-
- if (pa.EdotDotnet is not null)
- {
- @RenderProduct("EDOT .NET", "Elastic Distribution of OpenTelemetry .NET", VersioningSystemId.EdotDotnet, pa.EdotDotnet)
- }
-
- if (pa.EdotIos is not null)
- {
- @RenderProduct("EDOT iOS", "Elastic Distribution of OpenTelemetry iOS", VersioningSystemId.EdotIos, pa.EdotIos)
- }
-
- if (pa.EdotJava is not null)
- {
- @RenderProduct("EDOT Java", "Elastic Distribution of OpenTelemetry Java", VersioningSystemId.EdotJava, pa.EdotJava)
- }
-
- if (pa.EdotNode is not null)
- {
- @RenderProduct("EDOT Node.js", "Elastic Distribution of OpenTelemetry Node.js", VersioningSystemId.EdotNode, pa.EdotNode)
- }
-
- if (pa.EdotPhp is not null)
- {
- @RenderProduct("EDOT PHP", "Elastic Distribution of OpenTelemetry PHP", VersioningSystemId.ApmAgentPhp, pa.EdotPhp)
- }
-
- if (pa.EdotPython is not null)
- {
- @RenderProduct("EDOT Python", "Elastic Distribution of OpenTelemetry Python", VersioningSystemId.EdotPython, pa.EdotPython)
- }
-
- if (pa.ApmAgentAndroid is not null)
- {
- @RenderProduct("APM Agent Android", "Application Performance Monitoring Agent for Android", VersioningSystemId.ApmAgentAndroid, pa.ApmAgentAndroid)
- }
-
- if (pa.ApmAgentDotnet is not null)
- {
- @RenderProduct("APM Agent .NET", "Application Performance Monitoring Agent for .NET", VersioningSystemId.ApmAgentDotnet, pa.ApmAgentDotnet)
- }
-
- if (pa.ApmAgentGo is not null)
- {
- @RenderProduct("APM Agent Go", "Application Performance Monitoring Agent for Go", VersioningSystemId.ApmAgentGo, pa.ApmAgentGo)
- }
-
- if (pa.ApmAgentIos is not null)
- {
- @RenderProduct("APM Agent iOS", "Application Performance Monitoring Agent for iOS", VersioningSystemId.ApmAgentIos, pa.ApmAgentIos)
- }
-
- if (pa.ApmAgentJava is not null)
- {
- @RenderProduct("APM Agent Java", "Application Performance Monitoring Agent for Java", VersioningSystemId.ApmAgentJava, pa.ApmAgentJava)
- }
-
- if (pa.ApmAgentNode is not null)
- {
- @RenderProduct("APM Agent Node.js", "Application Performance Monitoring Agent for Node.js", VersioningSystemId.ApmAgentNode, pa.ApmAgentNode)
- }
-
- if (pa.ApmAgentPhp is not null)
- {
- @RenderProduct("APM Agent PHP", "Application Performance Monitoring Agent for PHP", VersioningSystemId.ApmAgentPhp, pa.ApmAgentPhp)
- }
-
- if (pa.ApmAgentPython is not null)
- {
- @RenderProduct("APM Agent Python", "Application Performance Monitoring Agent for Python", VersioningSystemId.ApmAgentPython, pa.ApmAgentPython)
- }
-
- if (pa.ApmAgentRuby is not null)
- {
- @RenderProduct("APM Agent Ruby", "Application Performance Monitoring Agent for Ruby", VersioningSystemId.ApmAgentRuby, pa.ApmAgentRuby)
- }
-
- if (pa.ApmAgentRum is not null)
- {
- @RenderProduct("APM Agent RUM", "Application Performance Monitoring Agent for Real User Monitoring", VersioningSystemId.ApmAgentRum, pa.ApmAgentRum)
- }
-}
-@if (appliesTo.Product is not null)
+@foreach (var item in Model.GetApplicabilityItems())
{
- @RenderProduct("", "", VersioningSystemId.All, appliesTo.Product)
-}
-
-@functions {
-
- private IHtmlContent RenderProduct(string key, string keyFull, VersioningSystemId versioningSystemName, AppliesCollection applications)
- {
- var versioningSystem = Model.VersionsConfig.GetVersioningSystem(versioningSystemName);
-
- foreach (var applicability in applications)
- {
- var badgeText = key;
- var tooltipText = "";
- var lifecycleClass = applicability.GetLifeCycleName().ToLowerInvariant().Replace(" ", "-");
+
+ @item.Key
- var lifecycleFull = applicability.Lifecycle switch
- {
- ProductLifecycle.GenerallyAvailable => "Available",
- ProductLifecycle.Beta => "Available in beta",
- ProductLifecycle.TechnicalPreview => "Available in technical preview",
- ProductLifecycle.Deprecated => "Deprecated",
- ProductLifecycle.Removed => "Removed",
- ProductLifecycle.Unavailable => "Not available",
- _ => ""
- };
-
- var realVersion = TryGetRealVersion(applicability, out var v) ? v : null;
-
- if (realVersion is not null)
- {
-
- if (realVersion <= versioningSystem.Current)
- {
- tooltipText = $"{lifecycleFull} on {keyFull} version {realVersion} and later unless otherwise specified.";
- }
- else
- {
- tooltipText = applicability.Lifecycle switch
- {
- ProductLifecycle.GenerallyAvailable
- or ProductLifecycle.Beta
- or ProductLifecycle.TechnicalPreview
- or ProductLifecycle.Planned =>
- $"We plan to add this functionality in a future {keyFull} update. Subject to change.",
- ProductLifecycle.Deprecated => $"We plan to deprecate this functionality in a future {keyFull} update. Subject to change.",
- ProductLifecycle.Removed => $"We plan to remove this functionality in a future {keyFull} update. Subject to change.",
- _ => tooltipText
- };
- }
-
- }
- else
+ @if (!string.IsNullOrEmpty(item.Key) && (item.RenderData.ShowLifecycle || item.RenderData.ShowVersion))
{
- tooltipText = $"{lifecycleFull} on {keyFull} unless otherwise specified.";
+
}
-
- var disclaimer = applicability.Lifecycle switch
- {
- ProductLifecycle.Beta => "Beta features are subject to change. The design and code is less mature than official GA features and is being provided as-is with no warranties. Beta features are not subject to the support SLA of official GA features.",
- ProductLifecycle.TechnicalPreview => "This functionality may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features.",
- ProductLifecycle.GenerallyAvailable => versioningSystem.Id is VersioningSystemId.Stack ? "If this functionality is unavailable or behaves differently when deployed on ECH, ECE, ECK, or a self-managed installation, it will be indicated on the page." : null,
- _ => null
- };
-
- if (disclaimer is not null)
- {
- tooltipText = $"{tooltipText}\n\n{disclaimer}";
- }
-
- if (realVersion is not null && realVersion > versioningSystem.Current)
- {
- badgeText = applicability.Lifecycle switch
+
+ @if (item.RenderData.ShowLifecycle)
{
- ProductLifecycle.TechnicalPreview => "Planned",
- ProductLifecycle.Beta => "Planned",
- ProductLifecycle.GenerallyAvailable =>
- applications.Any(a => a.Lifecycle is ProductLifecycle.TechnicalPreview or ProductLifecycle.Beta)
- ? "GA planned"
- : "Planned",
- ProductLifecycle.Deprecated => "Deprecation planned",
- ProductLifecycle.Removed => "Removal planned",
- ProductLifecycle.Planned => "Planned",
- _ => badgeText
- };
- }
-
- var badgeTextChanged = badgeText != key;
-
- @key
-
- @{
- var showLifeCycle = applicability.Lifecycle != ProductLifecycle.GenerallyAvailable && !badgeTextChanged;
- var showVersion = applicability.Version is not null and not AllVersions;
+ @item.Applicability.GetLifeCycleName()
}
-
- @if (!string.IsNullOrEmpty(key) && (showLifeCycle || showVersion))
+ @if (item.RenderData.ShowVersion)
{
-
- }
-
- @if (showLifeCycle)
+ @if (item.RenderData.ShowVersion && item.RenderData.Version != item.RenderData.BadgeText)
{
- @applicability.GetLifeCycleName()
+
+ @item.Applicability.Version
+
}
- @if (showVersion)
+ else
{
- @if (versioningSystem.Current >= applicability.Version!)
- {
-
- @applicability.Version
-
- }
- else
- {
- @badgeText
- }
+ @item.RenderData.BadgeText
}
-
+ }
- }
-
- return HtmlString.Empty;
- }
-
-}
-
-@functions {
-
- private static bool TryGetRealVersion(Applicability applicability, [NotNullWhen(true)] out SemVersion? version)
- {
- version = null;
- if (applicability.Version is not null && applicability.Version != AllVersions.Instance)
- {
- version = applicability.Version;
- return true;
- }
-
- return false;
- }
-
+
}
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs b/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
index 103226fb7..dab0318c0 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
+++ b/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
@@ -9,7 +9,176 @@ namespace Elastic.Markdown.Myst.Components;
public class ApplicableToViewModel
{
+ private readonly ApplicabilityRenderer _applicabilityRenderer = new();
+
public required bool Inline { get; init; }
public required ApplicableTo AppliesTo { get; init; }
public required VersionsConfiguration VersionsConfig { get; init; }
+
+ public IEnumerable GetApplicabilityItems()
+ {
+ var items = new List();
+
+ // Process Stack
+ if (AppliesTo.Stack is not null)
+ {
+ var productDef = ApplicabilityMappings.GetProductDefinition("stack");
+ var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(AppliesTo.Stack, productDef, versioningSystem));
+ }
+
+ // Process Serverless
+ if (AppliesTo.Serverless is not null)
+ {
+ if (AppliesTo.Serverless.AllProjects is not null)
+ {
+ var productDef = ApplicabilityMappings.GetProductDefinition("serverless");
+ var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(AppliesTo.Serverless.AllProjects, productDef, versioningSystem));
+ }
+ else
+ items.AddRange(ProcessServerlessProjects(AppliesTo.Serverless));
+ }
+
+ // Process Deployment
+ if (AppliesTo.Deployment is not null)
+ items.AddRange(ProcessDeploymentTypes(AppliesTo.Deployment));
+
+ // Process Product Applicability
+ if (AppliesTo.ProductApplicability is not null)
+ items.AddRange(ProcessProductApplicability(AppliesTo.ProductApplicability));
+
+ // Process Generic Product
+ if (AppliesTo.Product is not null)
+ {
+ var productDef = ApplicabilityMappings.GetProductDefinition("product");
+ var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(AppliesTo.Product, productDef, versioningSystem));
+ }
+
+ return items;
+ }
+
+ private IEnumerable ProcessServerlessProjects(ServerlessProjectApplicability serverless)
+ {
+ var items = new List();
+
+ if (serverless.Elasticsearch is not null)
+ {
+ var productDef = ApplicabilityMappings.GetProductDefinition("serverless-elasticsearch");
+ var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(serverless.Elasticsearch, productDef, versioningSystem));
+ }
+
+ if (serverless.Observability is not null)
+ {
+ var productDef = ApplicabilityMappings.GetProductDefinition("serverless-observability");
+ var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(serverless.Observability, productDef, versioningSystem));
+ }
+
+ if (serverless.Security is not null)
+ {
+ var productDef = ApplicabilityMappings.GetProductDefinition("serverless-security");
+ var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(serverless.Security, productDef, versioningSystem));
+ }
+
+ return items;
+ }
+
+ private IEnumerable ProcessDeploymentTypes(DeploymentApplicability deployment)
+ {
+ var items = new List();
+
+ if (deployment.Ess is not null)
+ {
+ var productDef = ApplicabilityMappings.GetProductDefinition("ech");
+ var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(deployment.Ess, productDef, versioningSystem));
+ }
+
+ if (deployment.Eck is not null)
+ {
+ var productDef = ApplicabilityMappings.GetProductDefinition("eck");
+ var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(deployment.Eck, productDef, versioningSystem));
+ }
+
+ if (deployment.Ece is not null)
+ {
+ var productDef = ApplicabilityMappings.GetProductDefinition("ece");
+ var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(deployment.Ece, productDef, versioningSystem));
+ }
+
+ if (deployment.Self is not null)
+ {
+ var productDef = ApplicabilityMappings.GetProductDefinition("self");
+ var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(deployment.Self, productDef, versioningSystem));
+ }
+
+ return items;
+ }
+
+ private IEnumerable ProcessProductApplicability(ProductApplicability productApplicability)
+ {
+ var items = new List();
+
+ // Process each product applicability property explicitly (AOT-compatible)
+ ProcessProductIfNotNull(productApplicability.Ecctl, "ecctl", items);
+ ProcessProductIfNotNull(productApplicability.Curator, "curator", items);
+ ProcessProductIfNotNull(productApplicability.EdotAndroid, "edot-android", items);
+ ProcessProductIfNotNull(productApplicability.EdotCfAws, "edot-cf-aws", items);
+ ProcessProductIfNotNull(productApplicability.EdotCollector, "edot-collector", items);
+ ProcessProductIfNotNull(productApplicability.EdotDotnet, "edot-dotnet", items);
+ ProcessProductIfNotNull(productApplicability.EdotIos, "edot-ios", items);
+ ProcessProductIfNotNull(productApplicability.EdotJava, "edot-java", items);
+ ProcessProductIfNotNull(productApplicability.EdotNode, "edot-node", items);
+ ProcessProductIfNotNull(productApplicability.EdotPhp, "edot-php", items);
+ ProcessProductIfNotNull(productApplicability.EdotPython, "edot-python", items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentAndroid, "apm-agent-android", items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentDotnet, "apm-agent-dotnet", items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentGo, "apm-agent-go", items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentIos, "apm-agent-ios", items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentJava, "apm-agent-java", items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentNode, "apm-agent-node", items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentPhp, "apm-agent-php", items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentPython, "apm-agent-python", items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentRuby, "apm-agent-ruby", items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentRum, "apm-agent-rum", items);
+
+ return items;
+ }
+
+ private void ProcessProductIfNotNull(AppliesCollection? collection, string productKey, List items)
+ {
+ if (collection is null)
+ return;
+
+ var applicabilityDefinition = ApplicabilityMappings.GetProductDefinition(productKey);
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDefinition.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(collection, applicabilityDefinition, versioningSystem));
+ }
+
+ private IEnumerable ProcessApplicabilityCollection(
+ AppliesCollection applications,
+ ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition,
+ VersioningSystem versioningSystem) =>
+ applications.Select(applicability =>
+ {
+ var renderData = _applicabilityRenderer.RenderApplicability(
+ applicability,
+ applicabilityDefinition,
+ versioningSystem,
+ applications);
+
+ return new ApplicabilityItem(
+ Key: applicabilityDefinition.Key,
+ Applicability: applicability,
+ RenderData: renderData
+ );
+ });
+
}
diff --git a/tests/authoring/Applicability/ApplicableToComponent.fs b/tests/authoring/Applicability/ApplicableToComponent.fs
index 7a8b50357..fc6c07223 100644
--- a/tests/authoring/Applicability/ApplicableToComponent.fs
+++ b/tests/authoring/Applicability/ApplicableToComponent.fs
@@ -507,6 +507,32 @@ product: ga
"""
+
+type ``product preview`` () =
+ static let markdown = Setup.Markdown """
+```{applies_to}
+product: preview 1.3.0
+```
+"""
+
+ []
+ let ``renders product preview`` () =
+ markdown |> convertsToHtml """
+
+
+
+
+ Preview
+
+ 1.3.0
+
+
+
+
+"""
+
// Test complex mixed scenarios
type ``complex mixed scenario`` () =
From e0ac169e06dad7d8f6ef54f84087b1ae4102a6ae Mon Sep 17 00:00:00 2001
From: Jan Calanog
Date: Fri, 12 Sep 2025 12:11:53 +0200
Subject: [PATCH 2/7] Update
src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
index 826d939e4..ad19e0ce5 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
+++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
@@ -39,7 +39,7 @@ public record ApplicabilityDefinition(string Key, string DisplayName, Versioning
["edot-ios"] = new ApplicabilityDefinition("EDOT iOS", "Elastic Distribution of OpenTelemetry iOS", VersioningSystemId.EdotIos),
["edot-java"] = new ApplicabilityDefinition("EDOT Java", "Elastic Distribution of OpenTelemetry Java", VersioningSystemId.EdotJava),
["edot-node"] = new ApplicabilityDefinition("EDOT Node.js", "Elastic Distribution of OpenTelemetry Node.js", VersioningSystemId.EdotNode),
- ["edot-php"] = new ApplicabilityDefinition("EDOT PHP", "Elastic Distribution of OpenTelemetry PHP", VersioningSystemId.ApmAgentPhp),
+ ["edot-php"] = new ApplicabilityDefinition("EDOT PHP", "Elastic Distribution of OpenTelemetry PHP", VersioningSystemId.EdotPhp),
["edot-python"] = new ApplicabilityDefinition("EDOT Python", "Elastic Distribution of OpenTelemetry Python", VersioningSystemId.EdotPython),
// APM Agents
From 3339962920ca1ebb8a05afef59c73f601ebd4126 Mon Sep 17 00:00:00 2001
From: Jan Calanog
Date: Fri, 12 Sep 2025 12:12:03 +0200
Subject: [PATCH 3/7] Update
src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---
.../Myst/Components/ApplicableToComponent.cshtml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml b/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
index 1a0ad590d..334fd8654 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
+++ b/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
@@ -16,7 +16,7 @@
}
@if (item.RenderData.ShowVersion)
{
- @if (item.RenderData.ShowVersion && item.RenderData.Version != item.RenderData.BadgeText)
+ @if (item.RenderData.Version != item.RenderData.BadgeText)
{
@item.Applicability.Version
From 327a2fa8cd578f715f442966a25b4c201bade466 Mon Sep 17 00:00:00 2001
From: Jan Calanog
Date: Fri, 12 Sep 2025 23:56:18 +0200
Subject: [PATCH 4/7] Fix naming
---
.../Myst/Components/ApplicabilityMappings.cs | 4 ++--
.../Myst/Components/ApplicableToViewModel.cs | 22 +++++++++----------
2 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
index ad19e0ce5..1dd50883c 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
+++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
@@ -58,7 +58,7 @@ public record ApplicabilityDefinition(string Key, string DisplayName, Versioning
["product"] = new ApplicabilityDefinition("", "", VersioningSystemId.All)
};
- public static ApplicabilityDefinition GetProductDefinition(string productKey) => Mappings.TryGetValue(productKey, out var definition)
+ public static ApplicabilityDefinition GetApplicabilityDefinition(string key) => Mappings.TryGetValue(key, out var definition)
? definition
- : throw new ArgumentException($"Unknown product key: {productKey}");
+ : throw new ArgumentException($"Unknown product key: {key}");
}
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs b/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
index dab0318c0..3dde4e0c8 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
+++ b/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
@@ -22,7 +22,7 @@ public IEnumerable GetApplicabilityItems()
// Process Stack
if (AppliesTo.Stack is not null)
{
- var productDef = ApplicabilityMappings.GetProductDefinition("stack");
+ var productDef = ApplicabilityMappings.GetApplicabilityDefinition("stack");
var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
items.AddRange(ProcessApplicabilityCollection(AppliesTo.Stack, productDef, versioningSystem));
}
@@ -32,7 +32,7 @@ public IEnumerable GetApplicabilityItems()
{
if (AppliesTo.Serverless.AllProjects is not null)
{
- var productDef = ApplicabilityMappings.GetProductDefinition("serverless");
+ var productDef = ApplicabilityMappings.GetApplicabilityDefinition("serverless");
var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
items.AddRange(ProcessApplicabilityCollection(AppliesTo.Serverless.AllProjects, productDef, versioningSystem));
}
@@ -51,7 +51,7 @@ public IEnumerable GetApplicabilityItems()
// Process Generic Product
if (AppliesTo.Product is not null)
{
- var productDef = ApplicabilityMappings.GetProductDefinition("product");
+ var productDef = ApplicabilityMappings.GetApplicabilityDefinition("product");
var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
items.AddRange(ProcessApplicabilityCollection(AppliesTo.Product, productDef, versioningSystem));
}
@@ -65,21 +65,21 @@ private IEnumerable ProcessServerlessProjects(ServerlessProje
if (serverless.Elasticsearch is not null)
{
- var productDef = ApplicabilityMappings.GetProductDefinition("serverless-elasticsearch");
+ var productDef = ApplicabilityMappings.GetApplicabilityDefinition("serverless-elasticsearch");
var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
items.AddRange(ProcessApplicabilityCollection(serverless.Elasticsearch, productDef, versioningSystem));
}
if (serverless.Observability is not null)
{
- var productDef = ApplicabilityMappings.GetProductDefinition("serverless-observability");
+ var productDef = ApplicabilityMappings.GetApplicabilityDefinition("serverless-observability");
var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
items.AddRange(ProcessApplicabilityCollection(serverless.Observability, productDef, versioningSystem));
}
if (serverless.Security is not null)
{
- var productDef = ApplicabilityMappings.GetProductDefinition("serverless-security");
+ var productDef = ApplicabilityMappings.GetApplicabilityDefinition("serverless-security");
var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
items.AddRange(ProcessApplicabilityCollection(serverless.Security, productDef, versioningSystem));
}
@@ -93,28 +93,28 @@ private IEnumerable ProcessDeploymentTypes(DeploymentApplicab
if (deployment.Ess is not null)
{
- var productDef = ApplicabilityMappings.GetProductDefinition("ech");
+ var productDef = ApplicabilityMappings.GetApplicabilityDefinition("ech");
var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
items.AddRange(ProcessApplicabilityCollection(deployment.Ess, productDef, versioningSystem));
}
if (deployment.Eck is not null)
{
- var productDef = ApplicabilityMappings.GetProductDefinition("eck");
+ var productDef = ApplicabilityMappings.GetApplicabilityDefinition("eck");
var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
items.AddRange(ProcessApplicabilityCollection(deployment.Eck, productDef, versioningSystem));
}
if (deployment.Ece is not null)
{
- var productDef = ApplicabilityMappings.GetProductDefinition("ece");
+ var productDef = ApplicabilityMappings.GetApplicabilityDefinition("ece");
var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
items.AddRange(ProcessApplicabilityCollection(deployment.Ece, productDef, versioningSystem));
}
if (deployment.Self is not null)
{
- var productDef = ApplicabilityMappings.GetProductDefinition("self");
+ var productDef = ApplicabilityMappings.GetApplicabilityDefinition("self");
var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
items.AddRange(ProcessApplicabilityCollection(deployment.Self, productDef, versioningSystem));
}
@@ -157,7 +157,7 @@ private void ProcessProductIfNotNull(AppliesCollection? collection, string produ
if (collection is null)
return;
- var applicabilityDefinition = ApplicabilityMappings.GetProductDefinition(productKey);
+ var applicabilityDefinition = ApplicabilityMappings.GetApplicabilityDefinition(productKey);
var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDefinition.VersioningSystemId);
items.AddRange(ProcessApplicabilityCollection(collection, applicabilityDefinition, versioningSystem));
}
From 19d04d5679fdc3f6daaab2a2a43e99774d5ca374 Mon Sep 17 00:00:00 2001
From: Jan Calanog
Date: Sun, 14 Sep 2025 00:25:18 +0200
Subject: [PATCH 5/7] Simplify a bit
---
.../Myst/Components/ApplicabilityRenderer.cs | 28 ++++++++-----------
.../Components/ApplicableToComponent.cshtml | 21 ++++++--------
2 files changed, 20 insertions(+), 29 deletions(-)
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs
index 11e22e297..87a683c89 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs
+++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs
@@ -12,11 +12,11 @@ namespace Elastic.Markdown.Myst.Components;
public class ApplicabilityRenderer
{
public record ApplicabilityRenderData(
- string BadgeText,
+ string BadgeLifecycleText,
string Version,
string TooltipText,
string LifecycleClass,
- bool ShowLifecycle,
+ bool ShowLifecycleName,
bool ShowVersion
);
@@ -31,22 +31,17 @@ public ApplicabilityRenderData RenderApplicability(
var realVersion = TryGetRealVersion(applicability, out var v) ? v : null;
var tooltipText = BuildTooltipText(applicability, applicabilityDefinition, versioningSystem, realVersion, lifecycleFull);
- var badgeText = BuildBadgeText(applicability, applicabilityDefinition, versioningSystem, realVersion, allApplications);
- var badgeTextChanged = badgeText != applicabilityDefinition.Key;
-
- var showLifecycle = applicability.Lifecycle != ProductLifecycle.GenerallyAvailable && !badgeTextChanged;
- var showVersion = applicability.Version is not null and not AllVersions;
-
- var version = showVersion && versioningSystem.Current >= applicability.Version!
- ? applicability.Version!.ToString()
- : badgeText;
+ var badgeLifecycleText = BuildBadgeLifecycleText(applicability, versioningSystem, realVersion, allApplications);
+ var showLifecycle = applicability.Lifecycle != ProductLifecycle.GenerallyAvailable && string.IsNullOrEmpty(badgeLifecycleText);
+ var showVersion = applicability.Version is not null and not AllVersions && versioningSystem.Current >= applicability.Version;
+ var version = applicability.Version?.ToString() ?? "";
return new ApplicabilityRenderData(
- BadgeText: badgeText,
+ BadgeLifecycleText: badgeLifecycleText,
Version: version,
TooltipText: tooltipText,
LifecycleClass: lifecycleClass,
- ShowLifecycle: showLifecycle,
+ ShowLifecycleName: showLifecycle,
ShowVersion: showVersion
);
}
@@ -104,15 +99,13 @@ or ProductLifecycle.TechnicalPreview
_ => null
};
- private static string BuildBadgeText(
+ private static string BuildBadgeLifecycleText(
Applicability applicability,
- ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition,
VersioningSystem versioningSystem,
SemVersion? realVersion,
AppliesCollection allApplications)
{
- var badgeText = applicabilityDefinition.Key;
-
+ var badgeText = "";
if (realVersion is not null && realVersion > versioningSystem.Current)
{
badgeText = applicability.Lifecycle switch
@@ -126,6 +119,7 @@ private static string BuildBadgeText(
ProductLifecycle.Deprecated => "Deprecation planned",
ProductLifecycle.Removed => "Removal planned",
ProductLifecycle.Planned => "Planned",
+ ProductLifecycle.Unavailable => "Unavailable",
_ => badgeText
};
}
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml b/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
index 334fd8654..f35d221e9 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
+++ b/src/Elastic.Markdown/Myst/Components/ApplicableToComponent.cshtml
@@ -5,27 +5,24 @@
@item.Key
- @if (!string.IsNullOrEmpty(item.Key) && (item.RenderData.ShowLifecycle || item.RenderData.ShowVersion))
+ @if (!string.IsNullOrEmpty(item.Key) && (item.RenderData.ShowLifecycleName || item.RenderData.ShowVersion || !string.IsNullOrEmpty(item.RenderData.BadgeLifecycleText)))
{
}
- @if (item.RenderData.ShowLifecycle)
+ @if (item.RenderData.ShowLifecycleName)
{
@item.Applicability.GetLifeCycleName()
}
@if (item.RenderData.ShowVersion)
{
- @if (item.RenderData.Version != item.RenderData.BadgeText)
- {
-
- @item.Applicability.Version
-
- }
- else
- {
- @item.RenderData.BadgeText
- }
+
+ @item.RenderData.Version
+
+ }
+ else
+ {
+ @item.RenderData.BadgeLifecycleText
}
From 324d1e1050713e8693f768c0c107845a009ae32b Mon Sep 17 00:00:00 2001
From: Jan Calanog
Date: Sun, 14 Sep 2025 21:04:55 +0200
Subject: [PATCH 6/7] Use properties instead of dictionary
---
.../Myst/Components/ApplicabilityMappings.cs | 95 +++++++---------
.../Myst/Components/ApplicableToViewModel.cs | 107 +++++++++---------
2 files changed, 97 insertions(+), 105 deletions(-)
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs b/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
index 1dd50883c..138b04a0f 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
+++ b/src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
@@ -10,55 +10,48 @@ public static class ApplicabilityMappings
{
public record ApplicabilityDefinition(string Key, string DisplayName, VersioningSystemId VersioningSystemId);
- private static readonly Dictionary Mappings = new()
- {
- // Stack
- ["stack"] = new ApplicabilityDefinition("Stack", "Elastic Stack", VersioningSystemId.Stack),
-
- // Serverless
- ["serverless"] = new ApplicabilityDefinition("Serverless", "Elastic Cloud Serverless", VersioningSystemId.Serverless),
- ["serverless-elasticsearch"] = new ApplicabilityDefinition("Serverless Elasticsearch", "Serverless Elasticsearch projects", VersioningSystemId.ElasticsearchProject),
- ["serverless-observability"] = new ApplicabilityDefinition("Serverless Observability", "Serverless Observability projects", VersioningSystemId.ObservabilityProject),
- ["serverless-security"] = new ApplicabilityDefinition("Serverless Security", "Serverless Security projects", VersioningSystemId.SecurityProject),
-
- // Deployment
- ["ech"] = new ApplicabilityDefinition("ECH", "Elastic Cloud Hosted", VersioningSystemId.Ess),
- ["eck"] = new ApplicabilityDefinition("ECK", "Elastic Cloud on Kubernetes", VersioningSystemId.Eck),
- ["ece"] = new ApplicabilityDefinition("ECE", "Elastic Cloud Enterprise", VersioningSystemId.Ece),
- ["self"] = new ApplicabilityDefinition("Self-Managed", "Self-managed Elastic deployments", VersioningSystemId.Self),
-
- // Product Applicability
- ["ecctl"] = new ApplicabilityDefinition("ECCTL", "Elastic Cloud Control", VersioningSystemId.Ecctl),
- ["curator"] = new ApplicabilityDefinition("Curator", "Curator", VersioningSystemId.Curator),
-
- // EDOT Products
- ["edot-android"] = new ApplicabilityDefinition("EDOT Android", "Elastic Distribution of OpenTelemetry Android", VersioningSystemId.EdotAndroid),
- ["edot-cf-aws"] = new ApplicabilityDefinition("EDOT CF AWS", "Elastic Distribution of OpenTelemetry Cloud Forwarder for AWS", VersioningSystemId.EdotCfAws),
- ["edot-collector"] = new ApplicabilityDefinition("EDOT Collector", "Elastic Distribution of OpenTelemetry Collector", VersioningSystemId.EdotCollector),
- ["edot-dotnet"] = new ApplicabilityDefinition("EDOT .NET", "Elastic Distribution of OpenTelemetry .NET", VersioningSystemId.EdotDotnet),
- ["edot-ios"] = new ApplicabilityDefinition("EDOT iOS", "Elastic Distribution of OpenTelemetry iOS", VersioningSystemId.EdotIos),
- ["edot-java"] = new ApplicabilityDefinition("EDOT Java", "Elastic Distribution of OpenTelemetry Java", VersioningSystemId.EdotJava),
- ["edot-node"] = new ApplicabilityDefinition("EDOT Node.js", "Elastic Distribution of OpenTelemetry Node.js", VersioningSystemId.EdotNode),
- ["edot-php"] = new ApplicabilityDefinition("EDOT PHP", "Elastic Distribution of OpenTelemetry PHP", VersioningSystemId.EdotPhp),
- ["edot-python"] = new ApplicabilityDefinition("EDOT Python", "Elastic Distribution of OpenTelemetry Python", VersioningSystemId.EdotPython),
-
- // APM Agents
- ["apm-agent-android"] = new ApplicabilityDefinition("APM Agent Android", "Application Performance Monitoring Agent for Android", VersioningSystemId.ApmAgentAndroid),
- ["apm-agent-dotnet"] = new ApplicabilityDefinition("APM Agent .NET", "Application Performance Monitoring Agent for .NET", VersioningSystemId.ApmAgentDotnet),
- ["apm-agent-go"] = new ApplicabilityDefinition("APM Agent Go", "Application Performance Monitoring Agent for Go", VersioningSystemId.ApmAgentGo),
- ["apm-agent-ios"] = new ApplicabilityDefinition("APM Agent iOS", "Application Performance Monitoring Agent for iOS", VersioningSystemId.ApmAgentIos),
- ["apm-agent-java"] = new ApplicabilityDefinition("APM Agent Java", "Application Performance Monitoring Agent for Java", VersioningSystemId.ApmAgentJava),
- ["apm-agent-node"] = new ApplicabilityDefinition("APM Agent Node.js", "Application Performance Monitoring Agent for Node.js", VersioningSystemId.ApmAgentNode),
- ["apm-agent-php"] = new ApplicabilityDefinition("APM Agent PHP", "Application Performance Monitoring Agent for PHP", VersioningSystemId.ApmAgentPhp),
- ["apm-agent-python"] = new ApplicabilityDefinition("APM Agent Python", "Application Performance Monitoring Agent for Python", VersioningSystemId.ApmAgentPython),
- ["apm-agent-ruby"] = new ApplicabilityDefinition("APM Agent Ruby", "Application Performance Monitoring Agent for Ruby", VersioningSystemId.ApmAgentRuby),
- ["apm-agent-rum"] = new ApplicabilityDefinition("APM Agent RUM", "Application Performance Monitoring Agent for Real User Monitoring", VersioningSystemId.ApmAgentRum),
-
- // Generic product
- ["product"] = new ApplicabilityDefinition("", "", VersioningSystemId.All)
- };
-
- public static ApplicabilityDefinition GetApplicabilityDefinition(string key) => Mappings.TryGetValue(key, out var definition)
- ? definition
- : throw new ArgumentException($"Unknown product key: {key}");
+ // Stack
+ public static readonly ApplicabilityDefinition Stack = new("Stack", "Elastic Stack", VersioningSystemId.Stack);
+
+ // Serverless
+ public static readonly ApplicabilityDefinition Serverless = new("Serverless", "Elastic Cloud Serverless", VersioningSystemId.Serverless);
+ public static readonly ApplicabilityDefinition ServerlessElasticsearch = new("Serverless Elasticsearch", "Serverless Elasticsearch projects", VersioningSystemId.ElasticsearchProject);
+ public static readonly ApplicabilityDefinition ServerlessObservability = new("Serverless Observability", "Serverless Observability projects", VersioningSystemId.ObservabilityProject);
+ public static readonly ApplicabilityDefinition ServerlessSecurity = new("Serverless Security", "Serverless Security projects", VersioningSystemId.SecurityProject);
+
+ // Deployment
+ public static readonly ApplicabilityDefinition Ech = new("ECH", "Elastic Cloud Hosted", VersioningSystemId.Ess);
+ public static readonly ApplicabilityDefinition Eck = new("ECK", "Elastic Cloud on Kubernetes", VersioningSystemId.Eck);
+ public static readonly ApplicabilityDefinition Ece = new("ECE", "Elastic Cloud Enterprise", VersioningSystemId.Ece);
+ public static readonly ApplicabilityDefinition Self = new("Self-Managed", "Self-managed Elastic deployments", VersioningSystemId.Self);
+
+ // Product Applicability
+ public static readonly ApplicabilityDefinition Ecctl = new("ECCTL", "Elastic Cloud Control", VersioningSystemId.Ecctl);
+ public static readonly ApplicabilityDefinition Curator = new("Curator", "Curator", VersioningSystemId.Curator);
+
+ // EDOT Products
+ public static readonly ApplicabilityDefinition EdotAndroid = new("EDOT Android", "Elastic Distribution of OpenTelemetry Android", VersioningSystemId.EdotAndroid);
+ public static readonly ApplicabilityDefinition EdotCfAws = new("EDOT CF AWS", "Elastic Distribution of OpenTelemetry Cloud Forwarder for AWS", VersioningSystemId.EdotCfAws);
+ public static readonly ApplicabilityDefinition EdotCollector = new("EDOT Collector", "Elastic Distribution of OpenTelemetry Collector", VersioningSystemId.EdotCollector);
+ public static readonly ApplicabilityDefinition EdotDotnet = new("EDOT .NET", "Elastic Distribution of OpenTelemetry .NET", VersioningSystemId.EdotDotnet);
+ public static readonly ApplicabilityDefinition EdotIos = new("EDOT iOS", "Elastic Distribution of OpenTelemetry iOS", VersioningSystemId.EdotIos);
+ public static readonly ApplicabilityDefinition EdotJava = new("EDOT Java", "Elastic Distribution of OpenTelemetry Java", VersioningSystemId.EdotJava);
+ public static readonly ApplicabilityDefinition EdotNode = new("EDOT Node.js", "Elastic Distribution of OpenTelemetry Node.js", VersioningSystemId.EdotNode);
+ public static readonly ApplicabilityDefinition EdotPhp = new("EDOT PHP", "Elastic Distribution of OpenTelemetry PHP", VersioningSystemId.EdotPhp);
+ public static readonly ApplicabilityDefinition EdotPython = new("EDOT Python", "Elastic Distribution of OpenTelemetry Python", VersioningSystemId.EdotPython);
+
+ // APM Agents
+ public static readonly ApplicabilityDefinition ApmAgentAndroid = new("APM Agent Android", "Application Performance Monitoring Agent for Android", VersioningSystemId.ApmAgentAndroid);
+ public static readonly ApplicabilityDefinition ApmAgentDotnet = new("APM Agent .NET", "Application Performance Monitoring Agent for .NET", VersioningSystemId.ApmAgentDotnet);
+ public static readonly ApplicabilityDefinition ApmAgentGo = new("APM Agent Go", "Application Performance Monitoring Agent for Go", VersioningSystemId.ApmAgentGo);
+ public static readonly ApplicabilityDefinition ApmAgentIos = new("APM Agent iOS", "Application Performance Monitoring Agent for iOS", VersioningSystemId.ApmAgentIos);
+ public static readonly ApplicabilityDefinition ApmAgentJava = new("APM Agent Java", "Application Performance Monitoring Agent for Java", VersioningSystemId.ApmAgentJava);
+ public static readonly ApplicabilityDefinition ApmAgentNode = new("APM Agent Node.js", "Application Performance Monitoring Agent for Node.js", VersioningSystemId.ApmAgentNode);
+ public static readonly ApplicabilityDefinition ApmAgentPhp = new("APM Agent PHP", "Application Performance Monitoring Agent for PHP", VersioningSystemId.ApmAgentPhp);
+ public static readonly ApplicabilityDefinition ApmAgentPython = new("APM Agent Python", "Application Performance Monitoring Agent for Python", VersioningSystemId.ApmAgentPython);
+ public static readonly ApplicabilityDefinition ApmAgentRuby = new("APM Agent Ruby", "Application Performance Monitoring Agent for Ruby", VersioningSystemId.ApmAgentRuby);
+ public static readonly ApplicabilityDefinition ApmAgentRum = new("APM Agent RUM", "Application Performance Monitoring Agent for Real User Monitoring", VersioningSystemId.ApmAgentRum);
+
+ // Generic product
+ public static readonly ApplicabilityDefinition Product = new("", "", VersioningSystemId.All);
}
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs b/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
index 3dde4e0c8..b2b231345 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
+++ b/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
@@ -22,9 +22,9 @@ public IEnumerable GetApplicabilityItems()
// Process Stack
if (AppliesTo.Stack is not null)
{
- var productDef = ApplicabilityMappings.GetApplicabilityDefinition("stack");
- var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(AppliesTo.Stack, productDef, versioningSystem));
+ var applicabilityDef = ApplicabilityMappings.Stack;
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(AppliesTo.Stack, applicabilityDef, versioningSystem));
}
// Process Serverless
@@ -32,9 +32,9 @@ public IEnumerable GetApplicabilityItems()
{
if (AppliesTo.Serverless.AllProjects is not null)
{
- var productDef = ApplicabilityMappings.GetApplicabilityDefinition("serverless");
- var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(AppliesTo.Serverless.AllProjects, productDef, versioningSystem));
+ var applicabilityDef = ApplicabilityMappings.Serverless;
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(AppliesTo.Serverless.AllProjects, applicabilityDef, versioningSystem));
}
else
items.AddRange(ProcessServerlessProjects(AppliesTo.Serverless));
@@ -51,9 +51,9 @@ public IEnumerable GetApplicabilityItems()
// Process Generic Product
if (AppliesTo.Product is not null)
{
- var productDef = ApplicabilityMappings.GetApplicabilityDefinition("product");
- var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(AppliesTo.Product, productDef, versioningSystem));
+ var applicabilityDef = ApplicabilityMappings.Product;
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(AppliesTo.Product, applicabilityDef, versioningSystem));
}
return items;
@@ -65,23 +65,23 @@ private IEnumerable ProcessServerlessProjects(ServerlessProje
if (serverless.Elasticsearch is not null)
{
- var productDef = ApplicabilityMappings.GetApplicabilityDefinition("serverless-elasticsearch");
- var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(serverless.Elasticsearch, productDef, versioningSystem));
+ var applicabilityDef = ApplicabilityMappings.ServerlessElasticsearch;
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(serverless.Elasticsearch, applicabilityDef, versioningSystem));
}
if (serverless.Observability is not null)
{
- var productDef = ApplicabilityMappings.GetApplicabilityDefinition("serverless-observability");
- var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(serverless.Observability, productDef, versioningSystem));
+ var applicabilityDef = ApplicabilityMappings.ServerlessObservability;
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(serverless.Observability, applicabilityDef, versioningSystem));
}
if (serverless.Security is not null)
{
- var productDef = ApplicabilityMappings.GetApplicabilityDefinition("serverless-security");
- var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(serverless.Security, productDef, versioningSystem));
+ var applicabilityDef = ApplicabilityMappings.ServerlessSecurity;
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(serverless.Security, applicabilityDef, versioningSystem));
}
return items;
@@ -93,30 +93,30 @@ private IEnumerable ProcessDeploymentTypes(DeploymentApplicab
if (deployment.Ess is not null)
{
- var productDef = ApplicabilityMappings.GetApplicabilityDefinition("ech");
- var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(deployment.Ess, productDef, versioningSystem));
+ var applicabilityDef = ApplicabilityMappings.Ech;
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(deployment.Ess, applicabilityDef, versioningSystem));
}
if (deployment.Eck is not null)
{
- var productDef = ApplicabilityMappings.GetApplicabilityDefinition("eck");
- var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(deployment.Eck, productDef, versioningSystem));
+ var applicabilityDef = ApplicabilityMappings.Eck;
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(deployment.Eck, applicabilityDef, versioningSystem));
}
if (deployment.Ece is not null)
{
- var productDef = ApplicabilityMappings.GetApplicabilityDefinition("ece");
- var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(deployment.Ece, productDef, versioningSystem));
+ var applicabilityDef = ApplicabilityMappings.Ece;
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(deployment.Ece, applicabilityDef, versioningSystem));
}
if (deployment.Self is not null)
{
- var productDef = ApplicabilityMappings.GetApplicabilityDefinition("self");
- var versioningSystem = VersionsConfig.GetVersioningSystem(productDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(deployment.Self, productDef, versioningSystem));
+ var applicabilityDef = ApplicabilityMappings.Self;
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
+ items.AddRange(ProcessApplicabilityCollection(deployment.Self, applicabilityDef, versioningSystem));
}
return items;
@@ -126,38 +126,37 @@ private IEnumerable ProcessProductApplicability(ProductApplic
{
var items = new List();
- // Process each product applicability property explicitly (AOT-compatible)
- ProcessProductIfNotNull(productApplicability.Ecctl, "ecctl", items);
- ProcessProductIfNotNull(productApplicability.Curator, "curator", items);
- ProcessProductIfNotNull(productApplicability.EdotAndroid, "edot-android", items);
- ProcessProductIfNotNull(productApplicability.EdotCfAws, "edot-cf-aws", items);
- ProcessProductIfNotNull(productApplicability.EdotCollector, "edot-collector", items);
- ProcessProductIfNotNull(productApplicability.EdotDotnet, "edot-dotnet", items);
- ProcessProductIfNotNull(productApplicability.EdotIos, "edot-ios", items);
- ProcessProductIfNotNull(productApplicability.EdotJava, "edot-java", items);
- ProcessProductIfNotNull(productApplicability.EdotNode, "edot-node", items);
- ProcessProductIfNotNull(productApplicability.EdotPhp, "edot-php", items);
- ProcessProductIfNotNull(productApplicability.EdotPython, "edot-python", items);
- ProcessProductIfNotNull(productApplicability.ApmAgentAndroid, "apm-agent-android", items);
- ProcessProductIfNotNull(productApplicability.ApmAgentDotnet, "apm-agent-dotnet", items);
- ProcessProductIfNotNull(productApplicability.ApmAgentGo, "apm-agent-go", items);
- ProcessProductIfNotNull(productApplicability.ApmAgentIos, "apm-agent-ios", items);
- ProcessProductIfNotNull(productApplicability.ApmAgentJava, "apm-agent-java", items);
- ProcessProductIfNotNull(productApplicability.ApmAgentNode, "apm-agent-node", items);
- ProcessProductIfNotNull(productApplicability.ApmAgentPhp, "apm-agent-php", items);
- ProcessProductIfNotNull(productApplicability.ApmAgentPython, "apm-agent-python", items);
- ProcessProductIfNotNull(productApplicability.ApmAgentRuby, "apm-agent-ruby", items);
- ProcessProductIfNotNull(productApplicability.ApmAgentRum, "apm-agent-rum", items);
+ // Process each product applicability property explicitly (AOT-compatible) using strongly-typed definitions
+ ProcessProductIfNotNull(productApplicability.Ecctl, ApplicabilityMappings.Ecctl, items);
+ ProcessProductIfNotNull(productApplicability.Curator, ApplicabilityMappings.Curator, items);
+ ProcessProductIfNotNull(productApplicability.EdotAndroid, ApplicabilityMappings.EdotAndroid, items);
+ ProcessProductIfNotNull(productApplicability.EdotCfAws, ApplicabilityMappings.EdotCfAws, items);
+ ProcessProductIfNotNull(productApplicability.EdotCollector, ApplicabilityMappings.EdotCollector, items);
+ ProcessProductIfNotNull(productApplicability.EdotDotnet, ApplicabilityMappings.EdotDotnet, items);
+ ProcessProductIfNotNull(productApplicability.EdotIos, ApplicabilityMappings.EdotIos, items);
+ ProcessProductIfNotNull(productApplicability.EdotJava, ApplicabilityMappings.EdotJava, items);
+ ProcessProductIfNotNull(productApplicability.EdotNode, ApplicabilityMappings.EdotNode, items);
+ ProcessProductIfNotNull(productApplicability.EdotPhp, ApplicabilityMappings.EdotPhp, items);
+ ProcessProductIfNotNull(productApplicability.EdotPython, ApplicabilityMappings.EdotPython, items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentAndroid, ApplicabilityMappings.ApmAgentAndroid, items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentDotnet, ApplicabilityMappings.ApmAgentDotnet, items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentGo, ApplicabilityMappings.ApmAgentGo, items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentIos, ApplicabilityMappings.ApmAgentIos, items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentJava, ApplicabilityMappings.ApmAgentJava, items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentNode, ApplicabilityMappings.ApmAgentNode, items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentPhp, ApplicabilityMappings.ApmAgentPhp, items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentPython, ApplicabilityMappings.ApmAgentPython, items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentRuby, ApplicabilityMappings.ApmAgentRuby, items);
+ ProcessProductIfNotNull(productApplicability.ApmAgentRum, ApplicabilityMappings.ApmAgentRum, items);
return items;
}
- private void ProcessProductIfNotNull(AppliesCollection? collection, string productKey, List items)
+ private void ProcessProductIfNotNull(AppliesCollection? collection, ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition, List items)
{
if (collection is null)
return;
- var applicabilityDefinition = ApplicabilityMappings.GetApplicabilityDefinition(productKey);
var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDefinition.VersioningSystemId);
items.AddRange(ProcessApplicabilityCollection(collection, applicabilityDefinition, versioningSystem));
}
From 6c2ffb841fc43976082e9c4711a7b02676eadf19 Mon Sep 17 00:00:00 2001
From: Jan Calanog
Date: Sun, 14 Sep 2025 21:46:50 +0200
Subject: [PATCH 7/7] Refactor repeating logic
---
.../Myst/Components/ApplicableToViewModel.cs | 172 +++++++-----------
1 file changed, 62 insertions(+), 110 deletions(-)
diff --git a/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs b/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
index b2b231345..ef50735ab 100644
--- a/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
+++ b/src/Elastic.Markdown/Myst/Components/ApplicableToViewModel.cs
@@ -15,152 +15,104 @@ public class ApplicableToViewModel
public required ApplicableTo AppliesTo { get; init; }
public required VersionsConfiguration VersionsConfig { get; init; }
+ // Dictionary mapping property selectors to their applicability definitions
+ private static readonly Dictionary, ApplicabilityMappings.ApplicabilityDefinition> DeploymentMappings = new()
+ {
+ [d => d.Ess] = ApplicabilityMappings.Ech,
+ [d => d.Eck] = ApplicabilityMappings.Eck,
+ [d => d.Ece] = ApplicabilityMappings.Ece,
+ [d => d.Self] = ApplicabilityMappings.Self
+ };
+
+ private static readonly Dictionary, ApplicabilityMappings.ApplicabilityDefinition> ServerlessMappings = new()
+ {
+ [s => s.Elasticsearch] = ApplicabilityMappings.ServerlessElasticsearch,
+ [s => s.Observability] = ApplicabilityMappings.ServerlessObservability,
+ [s => s.Security] = ApplicabilityMappings.ServerlessSecurity
+ };
+
+ private static readonly Dictionary, ApplicabilityMappings.ApplicabilityDefinition> ProductMappings = new()
+ {
+ [p => p.Ecctl] = ApplicabilityMappings.Ecctl,
+ [p => p.Curator] = ApplicabilityMappings.Curator,
+ [p => p.EdotAndroid] = ApplicabilityMappings.EdotAndroid,
+ [p => p.EdotCfAws] = ApplicabilityMappings.EdotCfAws,
+ [p => p.EdotCollector] = ApplicabilityMappings.EdotCollector,
+ [p => p.EdotDotnet] = ApplicabilityMappings.EdotDotnet,
+ [p => p.EdotIos] = ApplicabilityMappings.EdotIos,
+ [p => p.EdotJava] = ApplicabilityMappings.EdotJava,
+ [p => p.EdotNode] = ApplicabilityMappings.EdotNode,
+ [p => p.EdotPhp] = ApplicabilityMappings.EdotPhp,
+ [p => p.EdotPython] = ApplicabilityMappings.EdotPython,
+ [p => p.ApmAgentAndroid] = ApplicabilityMappings.ApmAgentAndroid,
+ [p => p.ApmAgentDotnet] = ApplicabilityMappings.ApmAgentDotnet,
+ [p => p.ApmAgentGo] = ApplicabilityMappings.ApmAgentGo,
+ [p => p.ApmAgentIos] = ApplicabilityMappings.ApmAgentIos,
+ [p => p.ApmAgentJava] = ApplicabilityMappings.ApmAgentJava,
+ [p => p.ApmAgentNode] = ApplicabilityMappings.ApmAgentNode,
+ [p => p.ApmAgentPhp] = ApplicabilityMappings.ApmAgentPhp,
+ [p => p.ApmAgentPython] = ApplicabilityMappings.ApmAgentPython,
+ [p => p.ApmAgentRuby] = ApplicabilityMappings.ApmAgentRuby,
+ [p => p.ApmAgentRum] = ApplicabilityMappings.ApmAgentRum
+ };
+
public IEnumerable GetApplicabilityItems()
{
var items = new List();
// Process Stack
if (AppliesTo.Stack is not null)
- {
- var applicabilityDef = ApplicabilityMappings.Stack;
- var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(AppliesTo.Stack, applicabilityDef, versioningSystem));
- }
+ items.AddRange(ProcessSingleCollection(AppliesTo.Stack, ApplicabilityMappings.Stack));
// Process Serverless
if (AppliesTo.Serverless is not null)
{
- if (AppliesTo.Serverless.AllProjects is not null)
- {
- var applicabilityDef = ApplicabilityMappings.Serverless;
- var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(AppliesTo.Serverless.AllProjects, applicabilityDef, versioningSystem));
- }
- else
- items.AddRange(ProcessServerlessProjects(AppliesTo.Serverless));
+ items.AddRange(AppliesTo.Serverless.AllProjects is not null
+ ? ProcessSingleCollection(AppliesTo.Serverless.AllProjects, ApplicabilityMappings.Serverless)
+ : ProcessMappedCollections(AppliesTo.Serverless, ServerlessMappings));
}
// Process Deployment
if (AppliesTo.Deployment is not null)
- items.AddRange(ProcessDeploymentTypes(AppliesTo.Deployment));
+ items.AddRange(ProcessMappedCollections(AppliesTo.Deployment, DeploymentMappings));
// Process Product Applicability
if (AppliesTo.ProductApplicability is not null)
- items.AddRange(ProcessProductApplicability(AppliesTo.ProductApplicability));
+ items.AddRange(ProcessMappedCollections(AppliesTo.ProductApplicability, ProductMappings));
// Process Generic Product
if (AppliesTo.Product is not null)
- {
- var applicabilityDef = ApplicabilityMappings.Product;
- var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(AppliesTo.Product, applicabilityDef, versioningSystem));
- }
+ items.AddRange(ProcessSingleCollection(AppliesTo.Product, ApplicabilityMappings.Product));
return items;
}
- private IEnumerable ProcessServerlessProjects(ServerlessProjectApplicability serverless)
+ ///
+ /// Processes a single collection with its corresponding applicability definition
+ ///
+ private IEnumerable ProcessSingleCollection(AppliesCollection collection, ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition)
{
- var items = new List();
-
- if (serverless.Elasticsearch is not null)
- {
- var applicabilityDef = ApplicabilityMappings.ServerlessElasticsearch;
- var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(serverless.Elasticsearch, applicabilityDef, versioningSystem));
- }
-
- if (serverless.Observability is not null)
- {
- var applicabilityDef = ApplicabilityMappings.ServerlessObservability;
- var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(serverless.Observability, applicabilityDef, versioningSystem));
- }
-
- if (serverless.Security is not null)
- {
- var applicabilityDef = ApplicabilityMappings.ServerlessSecurity;
- var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(serverless.Security, applicabilityDef, versioningSystem));
- }
-
- return items;
+ var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDefinition.VersioningSystemId);
+ return ProcessApplicabilityCollection(collection, applicabilityDefinition, versioningSystem);
}
- private IEnumerable ProcessDeploymentTypes(DeploymentApplicability deployment)
+ ///
+ /// Processes multiple collections using a mapping dictionary to eliminate repetitive code
+ ///
+ private IEnumerable ProcessMappedCollections(T source, Dictionary, ApplicabilityMappings.ApplicabilityDefinition> mappings)
{
var items = new List();
- if (deployment.Ess is not null)
- {
- var applicabilityDef = ApplicabilityMappings.Ech;
- var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(deployment.Ess, applicabilityDef, versioningSystem));
- }
-
- if (deployment.Eck is not null)
+ foreach (var (propertySelector, applicabilityDefinition) in mappings)
{
- var applicabilityDef = ApplicabilityMappings.Eck;
- var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(deployment.Eck, applicabilityDef, versioningSystem));
+ var collection = propertySelector(source);
+ if (collection is not null)
+ items.AddRange(ProcessSingleCollection(collection, applicabilityDefinition));
}
- if (deployment.Ece is not null)
- {
- var applicabilityDef = ApplicabilityMappings.Ece;
- var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(deployment.Ece, applicabilityDef, versioningSystem));
- }
-
- if (deployment.Self is not null)
- {
- var applicabilityDef = ApplicabilityMappings.Self;
- var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDef.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(deployment.Self, applicabilityDef, versioningSystem));
- }
-
- return items;
- }
-
- private IEnumerable ProcessProductApplicability(ProductApplicability productApplicability)
- {
- var items = new List();
-
- // Process each product applicability property explicitly (AOT-compatible) using strongly-typed definitions
- ProcessProductIfNotNull(productApplicability.Ecctl, ApplicabilityMappings.Ecctl, items);
- ProcessProductIfNotNull(productApplicability.Curator, ApplicabilityMappings.Curator, items);
- ProcessProductIfNotNull(productApplicability.EdotAndroid, ApplicabilityMappings.EdotAndroid, items);
- ProcessProductIfNotNull(productApplicability.EdotCfAws, ApplicabilityMappings.EdotCfAws, items);
- ProcessProductIfNotNull(productApplicability.EdotCollector, ApplicabilityMappings.EdotCollector, items);
- ProcessProductIfNotNull(productApplicability.EdotDotnet, ApplicabilityMappings.EdotDotnet, items);
- ProcessProductIfNotNull(productApplicability.EdotIos, ApplicabilityMappings.EdotIos, items);
- ProcessProductIfNotNull(productApplicability.EdotJava, ApplicabilityMappings.EdotJava, items);
- ProcessProductIfNotNull(productApplicability.EdotNode, ApplicabilityMappings.EdotNode, items);
- ProcessProductIfNotNull(productApplicability.EdotPhp, ApplicabilityMappings.EdotPhp, items);
- ProcessProductIfNotNull(productApplicability.EdotPython, ApplicabilityMappings.EdotPython, items);
- ProcessProductIfNotNull(productApplicability.ApmAgentAndroid, ApplicabilityMappings.ApmAgentAndroid, items);
- ProcessProductIfNotNull(productApplicability.ApmAgentDotnet, ApplicabilityMappings.ApmAgentDotnet, items);
- ProcessProductIfNotNull(productApplicability.ApmAgentGo, ApplicabilityMappings.ApmAgentGo, items);
- ProcessProductIfNotNull(productApplicability.ApmAgentIos, ApplicabilityMappings.ApmAgentIos, items);
- ProcessProductIfNotNull(productApplicability.ApmAgentJava, ApplicabilityMappings.ApmAgentJava, items);
- ProcessProductIfNotNull(productApplicability.ApmAgentNode, ApplicabilityMappings.ApmAgentNode, items);
- ProcessProductIfNotNull(productApplicability.ApmAgentPhp, ApplicabilityMappings.ApmAgentPhp, items);
- ProcessProductIfNotNull(productApplicability.ApmAgentPython, ApplicabilityMappings.ApmAgentPython, items);
- ProcessProductIfNotNull(productApplicability.ApmAgentRuby, ApplicabilityMappings.ApmAgentRuby, items);
- ProcessProductIfNotNull(productApplicability.ApmAgentRum, ApplicabilityMappings.ApmAgentRum, items);
-
return items;
}
- private void ProcessProductIfNotNull(AppliesCollection? collection, ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition, List items)
- {
- if (collection is null)
- return;
-
- var versioningSystem = VersionsConfig.GetVersioningSystem(applicabilityDefinition.VersioningSystemId);
- items.AddRange(ProcessApplicabilityCollection(collection, applicabilityDefinition, versioningSystem));
- }
-
private IEnumerable ProcessApplicabilityCollection(
AppliesCollection applications,
ApplicabilityMappings.ApplicabilityDefinition applicabilityDefinition,