+{
+ ///
+ public override void OnEnd(Activity activity)
+ {
+ ArgumentNullException.ThrowIfNull(activity);
+
+ // Only process server-side HTTP spans (inbound requests, not outbound HTTP client calls)
+ if (activity.Kind != ActivityKind.Server)
+ {
+ return;
+ }
+
+ // Bot user agents following stale links — 404s are expected, not actionable failures.
+ if (activity.GetTagItem("user_agent.original") is string userAgent
+ && userAgent.Contains("bot", StringComparison.OrdinalIgnoreCase))
+ {
+ activity.SetStatus(ActivityStatusCode.Ok);
+ return;
+ }
+ }
+}
diff --git a/src/TechHub.Web/Components/AddContentModal.razor b/src/TechHub.Web/Components/AddContentModal.razor
index d81aa9d7a..1593c6d95 100644
--- a/src/TechHub.Web/Components/AddContentModal.razor
+++ b/src/TechHub.Web/Components/AddContentModal.razor
@@ -421,11 +421,14 @@
var names = configs.Select(c => c.Name).Order(StringComparer.OrdinalIgnoreCase).ToList();
if (names.Count > 0)
{
- _feedNames = names;
+ // Always put TechHub first so it is the browser default regardless of
+ // Blazor render timing; remaining feeds stay alphabetical.
+ var rest = names.Where(n => !n.Equals(DefaultFeedName, StringComparison.OrdinalIgnoreCase)).ToList();
+ _feedNames = names.Any(n => n.Equals(DefaultFeedName, StringComparison.OrdinalIgnoreCase))
+ ? [DefaultFeedName, ..rest]
+ : names;
}
- var match = _feedNames.FirstOrDefault(
- n => n.Equals(DefaultFeedName, StringComparison.OrdinalIgnoreCase));
- _feedName = match ?? _feedNames[0];
+ _feedName = DefaultFeedName;
}
catch (HttpRequestException ex)
{
diff --git a/src/TechHub.Web/Components/ContentItemEditorModal.razor b/src/TechHub.Web/Components/ContentItemEditorModal.razor
index 6c86654e3..7b7bc5baf 100644
--- a/src/TechHub.Web/Components/ContentItemEditorModal.razor
+++ b/src/TechHub.Web/Components/ContentItemEditorModal.razor
@@ -44,6 +44,17 @@
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
@* ── Content ── *@
@@ -144,6 +158,7 @@
@@ -167,6 +182,7 @@
private string _searchFilter = string.Empty;
private string _collectionFilter = string.Empty;
private string _feedNameFilter = string.Empty;
+ private string _subcollectionFilter = string.Empty;
// Debounce timer for text input filters
private CancellationTokenSource? _debounce;
@@ -230,7 +246,8 @@
PageSize,
string.IsNullOrEmpty(_searchFilter) ? null : _searchFilter,
string.IsNullOrEmpty(_collectionFilter) ? null : _collectionFilter,
- string.IsNullOrEmpty(_feedNameFilter) ? null : _feedNameFilter);
+ string.IsNullOrEmpty(_feedNameFilter) ? null : _feedNameFilter,
+ string.IsNullOrEmpty(_subcollectionFilter) ? null : _subcollectionFilter);
UpdatePagination();
}
@@ -255,8 +272,14 @@
var feeds = await Api.GetFeedConfigsAsync();
_feedNames = feeds.Select(f => f.Name).OrderBy(n => n).ToList();
}
- catch
+ catch (HttpRequestException ex)
+ {
+ Logger.LogWarning(ex, "Failed to load feed names");
+ _feedNames = [];
+ }
+ catch (TaskCanceledException ex)
{
+ Logger.LogWarning(ex, "Failed to load feed names (timeout)");
_feedNames = [];
}
}
diff --git a/src/TechHub.Web/Components/Pages/Admin/AdminDashboard.razor b/src/TechHub.Web/Components/Pages/Admin/AdminDashboard.razor
index 898fe6d9a..17c1bf29c 100644
--- a/src/TechHub.Web/Components/Pages/Admin/AdminDashboard.razor
+++ b/src/TechHub.Web/Components/Pages/Admin/AdminDashboard.razor
@@ -155,7 +155,7 @@
}
- @if (job.JobType == ContentProcessingJobType.ContentProcessing)
+ @if (job.JobType is ContentProcessingJobType.ContentProcessing or ContentProcessingJobType.AdHocProcessing)
{
if (job.TranscriptsSucceeded > 0 || job.TranscriptsFailed > 0)
{
@@ -446,6 +446,7 @@
ContentProcessingJobType.ContentProcessing => "Processing",
ContentProcessingJobType.RoundupGeneration => "Roundup",
ContentProcessingJobType.ContentCleanup => "Cleanup",
+ ContentProcessingJobType.AdHocProcessing => "Ad-hoc",
_ => jobType
};
@@ -454,6 +455,7 @@
ContentProcessingJobType.ContentProcessing => "processing",
ContentProcessingJobType.RoundupGeneration => "roundup",
ContentProcessingJobType.ContentCleanup => "cleanup",
+ ContentProcessingJobType.AdHocProcessing => "adhoc",
_ => "unknown"
};
diff --git a/src/TechHub.Web/Components/Pages/Admin/AdminProcessedUrls.razor b/src/TechHub.Web/Components/Pages/Admin/AdminProcessedUrls.razor
index 126da0ced..8626ff556 100644
--- a/src/TechHub.Web/Components/Pages/Admin/AdminProcessedUrls.razor
+++ b/src/TechHub.Web/Components/Pages/Admin/AdminProcessedUrls.razor
@@ -7,6 +7,7 @@
@using TechHub.Web.Services
@implements IDisposable
@inject ITechHubApiClient Api
+@inject ILogger Logger
@inject PersistentComponentState ApplicationState
@inject IJSRuntime JS
@inject NavigationManager Navigation
@@ -68,8 +69,21 @@
-
+
+
+
+
+
@@ -167,6 +181,7 @@
@@ -189,6 +204,7 @@
private string _searchFilter = string.Empty;
private string _feedNameFilter = string.Empty;
private string _collectionFilter = string.Empty;
+ private string _subcollectionFilter = string.Empty;
private long? _jobIdFilter;
private string _jobIdFilterText = string.Empty;
@@ -266,7 +282,8 @@
string.IsNullOrEmpty(_searchFilter) ? null : _searchFilter,
string.IsNullOrEmpty(_feedNameFilter) ? null : _feedNameFilter,
string.IsNullOrEmpty(_collectionFilter) ? null : _collectionFilter,
- _jobIdFilter);
+ _jobIdFilter,
+ string.IsNullOrEmpty(_subcollectionFilter) ? null : _subcollectionFilter);
UpdatePagination();
await LoadFailedCountAsync();
@@ -305,8 +322,14 @@
var feeds = await Api.GetFeedConfigsAsync();
_feedNames = feeds.Select(f => f.Name).OrderBy(n => n).ToList();
}
- catch
+ catch (HttpRequestException ex)
+ {
+ Logger.LogWarning(ex, "Failed to load feed names");
+ _feedNames = [];
+ }
+ catch (TaskCanceledException ex)
{
+ Logger.LogWarning(ex, "Failed to load feed names (timeout)");
_feedNames = [];
}
}
diff --git a/src/TechHub.Web/Components/Pages/Admin/AdminReviews.razor b/src/TechHub.Web/Components/Pages/Admin/AdminReviews.razor
index ab8d0109e..4cbbe49b5 100644
--- a/src/TechHub.Web/Components/Pages/Admin/AdminReviews.razor
+++ b/src/TechHub.Web/Components/Pages/Admin/AdminReviews.razor
@@ -277,6 +277,7 @@
@@ -314,6 +315,7 @@
private ContentItemEditData? _editorData;
private string _editorCollectionName = string.Empty;
private string _editorSlug = string.Empty;
+ private IReadOnlyList ? _feedNames;
protected override async Task OnInitializedAsync()
{
@@ -330,6 +332,25 @@
await LoadDataAsync();
}
+ private async Task LoadFeedNamesAsync()
+ {
+ try
+ {
+ var feeds = await Api.GetFeedConfigsAsync();
+ _feedNames = feeds.Select(f => f.Name).OrderBy(n => n).ToList();
+ }
+ catch (HttpRequestException ex)
+ {
+ Logger.LogWarning(ex, "Failed to load feed names");
+ _feedNames = [];
+ }
+ catch (TaskCanceledException ex)
+ {
+ Logger.LogWarning(ex, "Failed to load feed names (timeout)");
+ _feedNames = [];
+ }
+ }
+
private Task PersistState()
{
if (_reviews != null)
@@ -587,6 +608,11 @@
_message = null;
try
{
+ if (_feedNames is null)
+ {
+ await LoadFeedNamesAsync();
+ }
+
var result = await Api.GetContentItemEditDataAsync(review.CollectionName, review.Slug);
if (result is null)
{
diff --git a/src/TechHub.Web/Components/Pages/Admin/AdminSettings.razor b/src/TechHub.Web/Components/Pages/Admin/AdminSettings.razor
index d4d82a5bd..e9935dc18 100644
--- a/src/TechHub.Web/Components/Pages/Admin/AdminSettings.razor
+++ b/src/TechHub.Web/Components/Pages/Admin/AdminSettings.razor
@@ -6,6 +6,7 @@
@implements IDisposable
@inject ITechHubApiClient Api
@inject SectionCache SectionCache
+@inject HeroBannerCache HeroBannerCache
@inject PersistentComponentState ApplicationState
@inject ILogger Logger
@@ -86,7 +87,7 @@
|