Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/Elastic.Markdown/Myst/Components/ApplicabilityItem.cs
Original file line number Diff line number Diff line change
@@ -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
);
64 changes: 64 additions & 0 deletions src/Elastic.Markdown/Myst/Components/ApplicabilityMappings.cs
Original file line number Diff line number Diff line change
@@ -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<string, ApplicabilityDefinition> Mappings = new()
{
// Stack
["stack"] = new ApplicabilityDefinition("Stack", "Elastic&nbsp;Stack", VersioningSystemId.Stack),

// Serverless
["serverless"] = new ApplicabilityDefinition("Serverless", "Elastic&nbsp;Cloud&nbsp;Serverless", VersioningSystemId.Serverless),
["serverless-elasticsearch"] = new ApplicabilityDefinition("Serverless Elasticsearch", "Serverless&nbsp;Elasticsearch projects", VersioningSystemId.ElasticsearchProject),
["serverless-observability"] = new ApplicabilityDefinition("Serverless Observability", "Serverless&nbsp;Observability projects", VersioningSystemId.ObservabilityProject),
["serverless-security"] = new ApplicabilityDefinition("Serverless Security", "Serverless&nbsp;Security projects", VersioningSystemId.SecurityProject),

// Deployment
["ech"] = new ApplicabilityDefinition("ECH", "Elastic&nbsp;Cloud&nbsp;Hosted", VersioningSystemId.Ess),
["eck"] = new ApplicabilityDefinition("ECK", "Elastic&nbsp;Cloud&nbsp;on&nbsp;Kubernetes", VersioningSystemId.Eck),
["ece"] = new ApplicabilityDefinition("ECE", "Elastic&nbsp;Cloud&nbsp;Enterprise", VersioningSystemId.Ece),
["self"] = new ApplicabilityDefinition("Self-Managed", "Self-managed Elastic&nbsp;deployments", VersioningSystemId.Self),

// Product Applicability
["ecctl"] = new ApplicabilityDefinition("ECCTL", "Elastic&nbsp;Cloud&nbsp;Control", VersioningSystemId.Ecctl),
["curator"] = new ApplicabilityDefinition("Curator", "Curator", VersioningSystemId.Curator),

// EDOT Products
["edot-android"] = new ApplicabilityDefinition("EDOT Android", "Elastic&nbsp;Distribution of OpenTelemetry&nbsp;Android", VersioningSystemId.EdotAndroid),
["edot-cf-aws"] = new ApplicabilityDefinition("EDOT CF AWS", "Elastic&nbsp;Distribution of OpenTelemetry&nbsp;Cloud&nbsp;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&nbsp;Distribution of OpenTelemetry&nbsp;.NET", VersioningSystemId.EdotDotnet),
["edot-ios"] = new ApplicabilityDefinition("EDOT iOS", "Elastic&nbsp;Distribution of OpenTelemetry&nbsp;iOS", VersioningSystemId.EdotIos),
["edot-java"] = new ApplicabilityDefinition("EDOT Java", "Elastic&nbsp;Distribution of OpenTelemetry&nbsp;Java", VersioningSystemId.EdotJava),
["edot-node"] = new ApplicabilityDefinition("EDOT Node.js", "Elastic&nbsp;Distribution of OpenTelemetry&nbsp;Node.js", VersioningSystemId.EdotNode),
["edot-php"] = new ApplicabilityDefinition("EDOT PHP", "Elastic&nbsp;Distribution of OpenTelemetry&nbsp;PHP", VersioningSystemId.EdotPhp),
["edot-python"] = new ApplicabilityDefinition("EDOT Python", "Elastic&nbsp;Distribution of OpenTelemetry&nbsp;Python", VersioningSystemId.EdotPython),

// APM Agents
["apm-agent-android"] = new ApplicabilityDefinition("APM Agent Android", "Application&nbsp;Performance&nbsp;Monitoring Agent for Android", VersioningSystemId.ApmAgentAndroid),
["apm-agent-dotnet"] = new ApplicabilityDefinition("APM Agent .NET", "Application&nbsp;Performance&nbsp;Monitoring Agent for .NET", VersioningSystemId.ApmAgentDotnet),
["apm-agent-go"] = new ApplicabilityDefinition("APM Agent Go", "Application&nbsp;Performance&nbsp;Monitoring Agent for Go", VersioningSystemId.ApmAgentGo),
["apm-agent-ios"] = new ApplicabilityDefinition("APM Agent iOS", "Application&nbsp;Performance&nbsp;Monitoring Agent for iOS", VersioningSystemId.ApmAgentIos),
["apm-agent-java"] = new ApplicabilityDefinition("APM Agent Java", "Application&nbsp;Performance&nbsp;Monitoring Agent for Java", VersioningSystemId.ApmAgentJava),
["apm-agent-node"] = new ApplicabilityDefinition("APM Agent Node.js", "Application&nbsp;Performance&nbsp;Monitoring Agent for Node.js", VersioningSystemId.ApmAgentNode),
["apm-agent-php"] = new ApplicabilityDefinition("APM Agent PHP", "Application&nbsp;Performance&nbsp;Monitoring Agent for PHP", VersioningSystemId.ApmAgentPhp),
["apm-agent-python"] = new ApplicabilityDefinition("APM Agent Python", "Application&nbsp;Performance&nbsp;Monitoring Agent for Python", VersioningSystemId.ApmAgentPython),
["apm-agent-ruby"] = new ApplicabilityDefinition("APM Agent Ruby", "Application&nbsp;Performance&nbsp;Monitoring Agent for Ruby", VersioningSystemId.ApmAgentRuby),
["apm-agent-rum"] = new ApplicabilityDefinition("APM Agent RUM", "Application&nbsp;Performance&nbsp;Monitoring Agent for Real&nbsp;User&nbsp;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}");
}
141 changes: 141 additions & 0 deletions src/Elastic.Markdown/Myst/Components/ApplicabilityRenderer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// 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 BadgeLifecycleText,
string Version,
string TooltipText,
string LifecycleClass,
bool ShowLifecycleName,
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 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(
BadgeLifecycleText: badgeLifecycleText,
Version: version,
TooltipText: tooltipText,
LifecycleClass: lifecycleClass,
ShowLifecycleName: 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 BuildBadgeLifecycleText(
Applicability applicability,
VersioningSystem versioningSystem,
SemVersion? realVersion,
AppliesCollection allApplications)
{
var badgeText = "";
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",
ProductLifecycle.Unavailable => "Unavailable",
_ => 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;
}
}
Loading
Loading