diff --git a/src/FluentCMS.Admin/AdminRoutes.cs b/src/FluentCMS.Admin/AdminRoutes.cs index 11522e772..18166eb05 100644 --- a/src/FluentCMS.Admin/AdminRoutes.cs +++ b/src/FluentCMS.Admin/AdminRoutes.cs @@ -1,6 +1,7 @@ namespace FluentCMS.Admin; -// The routes the host needs: the account pages for the cookie's redirects, and the audit page with the download it posts to. +// The routes the host needs: the account pages for the cookie's redirects, the audit page with the download it posts to, and the +// media library with its upload and file endpoints. // Each page route matches the @page directive of its page. public static class AdminRoutes { @@ -15,6 +16,15 @@ public static class AdminRoutes public const string Audit = "/audit"; public const string AuditExport = "/audit/export"; + // The media library page, and the endpoints a page cannot be: the upload its form posts to and the bytes its previews show. + public const string Media = "/media"; + public const string MediaUpload = "/media/upload"; + + public static string MediaFile(Guid id, int? version = null) + { + return version is { } number ? $"media/{id}/file?version={number}" : $"media/{id}/file"; + } + // Only a path on this site is followed after sign-in, so a crafted link cannot send someone elsewhere. public static bool IsLocal(string? url) { diff --git a/src/FluentCMS.Admin/Components/Layout/MainLayout.razor b/src/FluentCMS.Admin/Components/Layout/MainLayout.razor index f3918410b..8bb002efb 100644 --- a/src/FluentCMS.Admin/Components/Layout/MainLayout.razor +++ b/src/FluentCMS.Admin/Components/Layout/MainLayout.razor @@ -9,6 +9,7 @@ @if (Initiator.Current is UserInitiator user) { + @L["Media"] @L["Audit log"] @L["Users"] @L["Agents"] diff --git a/src/FluentCMS.Admin/Components/Pages/MediaAssetView.razor b/src/FluentCMS.Admin/Components/Pages/MediaAssetView.razor new file mode 100644 index 000000000..857265d58 --- /dev/null +++ b/src/FluentCMS.Admin/Components/Pages/MediaAssetView.razor @@ -0,0 +1,246 @@ +@page "/media/{Id:guid}" +@using System.Globalization +@using FluentCMS.Admin.Media +@using FluentCMS.Core.Content +@using FluentCMS.Core.Media +@inject IMediaLibrary Library +@inject IWhereUsed WhereUsed +@inject NavigationManager Navigation +@inject IStringLocalizer L + +@L["Media"] + +@if (_asset is { } asset) +{ + var latest = asset.Latest; + + +

@latest.Metadata.FileName

+
+ @latest.Blob.ContentType + @L["Version {0}", asset.LatestVersion] + @if (asset.PublishedVersion is { } published) + { + @L["Version {0} is published", published] + } + else + { + @L["Not published"] + } + @L["Download"] +
+ + @if (Uploaded) + { +

@L["Uploaded. The file is stored as version 1."]

+ } + +
+ + +

@L["Preview"]

+
+ + @if (latest.Blob.ContentType.StartsWith("image/", StringComparison.Ordinal)) + { + @(latest.Metadata.AltText ?? string.Empty) + @if (latest.Metadata.AltText is null) + { +

@L["This image has no alt text, so people who cannot see it do not know what it shows. Add it below."]

+ } + } + else + { +

@L["No preview for this type. Download the file to see it."]

+ } +
+
+ + + +

@L["Details"]

+ @L["Saving stores a new version with these details; the file stays the same."] +
+ +
+ + + @if (_message is not null) + { +

@_message

+ } + @if (_formError is not null) + { + + } + + + + + + + + + + +