summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJake Mannens <jake@asger.xyz>2026-05-25 01:06:59 +1000
committerJake Mannens <jake@asger.xyz>2026-06-11 01:13:32 +1000
commita932b1bcb946bd70a5eb3e8fe1857fb74210a76b (patch)
treec3377cb963026e68bd29e34a21a6d319f378dee7
parent96d44f2947fd3ebef78411f65b09bbd2110d215f (diff)
Re-implemented existing features via the API
-rw-r--r--Pages/Component/AboutDialog.razor44
-rw-r--r--Pages/Component/MediaTagTable.razor158
-rw-r--r--Pages/Component/TagSelectDialog.razor131
-rw-r--r--Pages/Component/Titlebar.razor7
-rw-r--r--Pages/TagDefinitions.razor77
-rw-r--r--Pages/ViewMedia.razor145
6 files changed, 316 insertions, 246 deletions
diff --git a/Pages/Component/AboutDialog.razor b/Pages/Component/AboutDialog.razor
index fa7b1ca..888040e 100644
--- a/Pages/Component/AboutDialog.razor
+++ b/Pages/Component/AboutDialog.razor
@@ -1,9 +1,7 @@
-@using System.Reflection
-@*
- * @using Microsoft.AspNetCore.Hosting
- * @inject IDbContextFactory<HBContext> dbFactory
- * @inject IHostingEnvironment hostingEnvironment
- *@
+@using Microsoft.AspNetCore.Components.WebAssembly.Hosting
+@using System.Reflection
+@inject IWebAssemblyHostEnvironment hostEnvironment
+@inject HBSession hb
@implements IDialog
<Dialog @ref=dialog>
@@ -676,10 +674,11 @@
</div>
<a href="https://gitlab.com/plasmicplexus/HyperBooru-Server" target="_blank">Source</a>
<div id="progressContainer">
- @if(progress.HasValue) {
- var untagged = progress.Value.Untagged.ToString("N0");
- var total = progress.Value.Total.ToString("N0");
- var percent = (progress.Value.Untagged * 100f / progress.Value.Total).ToString("f1");
+ @if(ingestStatistics is not null) {
+ var untagged = ingestStatistics.UntaggedMediaCount.ToString("N0");
+ var total = ingestStatistics.TotalMediaCount.ToString("N0");
+ var percent =
+ (ingestStatistics.UntaggedMediaCount * 100f / ingestStatistics.TotalMediaCount).ToString("f1");
<p id="progress">Untagged: @($"{untagged}/{total} ({percent}%)")</p>
}
<ProgressBar @ref=progressBar />
@@ -694,23 +693,15 @@
private ProgressBar progressBar;
- private (long Untagged, long Total)? progress;
+ private IngestStatistics? ingestStatistics;
public bool Visible {
get => dialog.Visible;
set {
dialog.Visible = value;
- if(value) {
- // using var db = dbFactory.CreateDbContext();
- // progress = (
- // Untagged: db.Media
- // .Where(m => m.Tags.Any(t => t.TagDefinition.ObjectId == (int) HBObjectId.IngestTag))
- // .Count(),
- // Total: db.Media.Count()
- // );
- // progressBar.Progress = (float) progress.Value!.Untagged / (float) progress.Value!.Total;
- // InvokeAsync(() => StateHasChanged());
- }
+ InvokeAsync(() => StateHasChanged());
+ if(value)
+ LoadProgressAsync();
}
}
@@ -731,8 +722,15 @@
#if DEBUG
return "(Development)";
#else
- return hostingEnvironment.IsDevelopment() ? "(Development)" : null;
+ return hostEnvironment.IsDevelopment() ? "(Development)" : null;
#endif
}
}
+
+ private async void LoadProgressAsync() {
+ ingestStatistics = await hb.Statistics.GetIngestStatisticsAsync();
+ progressBar.Progress =
+ (float) ingestStatistics.UntaggedMediaCount / (float) ingestStatistics.TotalMediaCount;
+ await InvokeAsync(() => StateHasChanged());
+ }
}
diff --git a/Pages/Component/MediaTagTable.razor b/Pages/Component/MediaTagTable.razor
index 0524739..5e60d20 100644
--- a/Pages/Component/MediaTagTable.razor
+++ b/Pages/Component/MediaTagTable.razor
@@ -1,75 +1,109 @@
@inject HBSession hb
-<table class="data-table">
- <tr>
- <th>Namespace</th>
- <th>Tag Name</th>
- <th></th>
- </tr>
- @foreach(var e in tagDefs) {
- <tr>
- <td>
- @if(e.isImplicit) {
- <i>@e.tagDef.Namespace</i>
- } else {
- @e.tagDef.Namespace
- }
- </td>
- <td>
- <a href="/Gallery?t=@(e.tagDef.TagDefinitionId)" class="nondecorated">
- @if(e.isImplicit) {
- <i>@e.tagDef.Name</i>
- } else {
- @e.tagDef.Name
- }
- </a>
- </td>
- <td>
- @if(!e.isImplicit) {
- <a href="javascript:;" @onclick=@(() => Delete(e.tagDef))>Delete</a>
- } else {
- <a href="javascript:;" @onclick=@(() => MakeExplicit(e.tagDef))>Make Explicit</a>
- }
- </td>
- </tr>
- }
-</table>
+<LoadableContent T="List<TagTableEntry>" DataSource=LoadTagDefs @ref=tagContent>
+ <LoadingState>
+ <p><i>Loading...</i></p>
+ </LoadingState>
+ <ErrorState>
+ <p><i>Unable to fetch tags for this item!</i></p>
+ </ErrorState>
+ <LoadedState>
+ <table class="data-table">
+ <tr>
+ <th>Namespace</th>
+ <th>Tag Name</th>
+ <th></th>
+ </tr>
+ @{
+ var tags = tagContent.Data.Where(td => td.TagDefinition.Source == TagSource.UserTag);
+ }
+ @foreach(var e in tags) {
+ <tr>
+ <td>
+ @if(e.IsImplicit) {
+ <i>@e.TagDefinition.Namespace</i>
+ } else {
+ @e.TagDefinition.Namespace
+ }
+ </td>
+ <td>
+ <a href="/Gallery?t=@(e.TagDefinition.TagDefinitionId)" class="nondecorated">
+ @if(e.IsImplicit) {
+ <i>@e.TagDefinition.Name</i>
+ } else {
+ @e.TagDefinition.Name
+ }
+ </a>
+ </td>
+ <td>
+ @if(!e.IsImplicit) {
+ <a href="javascript:;" @onclick=@(() => Delete(e.TagDefinition))>Delete</a>
+ } else {
+ <a href="javascript:;" @onclick=@(() => MakeExplicit(e.TagDefinition))>Make Explicit</a>
+ }
+ </td>
+ </tr>
+ }
+ </table>
+ </LoadedState>
+</LoadableContent>
@code {
- [Parameter]
- public Guid MediaId { get; set; }
+ [Parameter]
+ public Guid MediaId { get; set; }
- private (TagDefinition tagDef, bool isImplicit)[] tagDefs = [];
+ private LoadableContent<List<TagTableEntry>> tagContent;
- protected override void OnInitialized() => LoadTagDefs();
+ private void Delete(TagDefinition tagDef) {
+ // tagService.RemoveTag(Media.Guid, tagDef.Guid);
+ // Refresh();
+ }
- public void Refresh() {
- LoadTagDefs();
- // StateHasChanged();
- }
+ private async Task<List<TagTableEntry>> LoadTagDefs() {
+ var itemTags = await hb.Media.GetTagsAsync(MediaId);
+ var allTags = await hb.Tag.GetTagDefinitionAsync();
- private void Delete(TagDefinition tagDef) {
- // tagService.RemoveTag(Media.Guid, tagDef.Guid);
- // Refresh();
- }
+ var tags = itemTags
+ .Select(td => new TagTableEntry() {
+ TagDefinition = td,
+ IsImplicit = false
+ })
+ .ToList();
- private async void LoadTagDefs() {
- var tags = await hb.Media.GetTagsAsync(MediaId);
+ while(true) {
+ var toAdd = allTags
+ .IntersectBy(tags
+ .SelectMany(t => t.TagDefinition.ImplicitTags), td => td.TagDefinitionId)
+ .Where(td => !tags
+ .Select(t => t.TagDefinition.TagDefinitionId)
+ .Contains(td.TagDefinitionId));
+ if(toAdd.Count() == 0)
+ break;
+ tags.AddRange(toAdd.Select(td => new TagTableEntry() {
+ TagDefinition = td,
+ IsImplicit = true
+ }));
+ }
- tagDefs = tags.Select(td => (tagDef: td, isImplicit: false)).ToArray();
+ return tags
+ .OrderBy(td => td.IsImplicit)
+ .ThenBy(td => td.TagDefinition.Namespace)
+ .ThenBy(td => td.TagDefinition.Name)
+ .ToList();
+ }
- await InvokeAsync(() => StateHasChanged());
+ private async Task MakeExplicit(TagDefinition tagDef) {
+ // TODO: Add error handling
+ await hb.Media.AddTagsAsync(MediaId, [ tagDef.TagDefinitionId ]);
+ //var index =
+ // tagDefs.IndexOf(tagDefs.First(td => td.tagDef.TagDefinitionId == tagDef.TagDefinitionId));
+ //tagDefs[index].isImplicit = false;
+ tagContent.Load();
+ await InvokeAsync(() => StateHasChanged());
+ }
- // using var db = dbFactory.CreateDbContext();
- // var media = db.Media.First(m => m.ObjectId == Media.ObjectId);
-
- // tagDefs = tagService.GetAllTags(Media)
- // .Where(e => e.tagDefinition.Source == TagSource.UserTag)
- // .ToArray();
- }
-
- private void MakeExplicit(TagDefinition tagDef) {
- // tagService.AddTag(Media, tagDef);
- // Refresh();
- }
+ private record TagTableEntry {
+ internal required TagDefinition TagDefinition { get; set; }
+ internal required bool IsImplicit { get; set; }
+ }
}
diff --git a/Pages/Component/TagSelectDialog.razor b/Pages/Component/TagSelectDialog.razor
index 99321fe..5872ce7 100644
--- a/Pages/Component/TagSelectDialog.razor
+++ b/Pages/Component/TagSelectDialog.razor
@@ -3,49 +3,57 @@
* @inject ITagService tagService
* @inject IUserService userService
*@
+@inject HBSession hb
@implements IDisposable
@implements IDialog
-<link rel="stylesheet" href="@(nameof(HyperBooru)).styles.css"/>
-
<Dialog Title=@(Title ?? "Select one or more tag(s)") @ref=dialog>
- <input
- type="text"
- placeholder="Search"
- autocorrect="off"
- autocapitalize="off"
- autocomplete="off"
- @ref=queryInput
- @oninput=QueryInput
- @onkeypress=QueryKey
- value=@query/>
- <div class="tag-definitions">
- @for(int i = 0; i < tagDefinitions.Count(); i++) {
- if(!MatchesQuery(tagDefinitions[i].tagDefinition))
- continue;
- var local = i;
- var ns = tagDefinitions[i].tagDefinition.Namespace;
- var alias = tagDefinitions[i].tagDefinition.Alias;
- var title = string.Join(" ", new[] {
- ns,
- alias is not null ? $"({alias})" : null
- });
-@*
- <input
- type="checkbox"
- id="tagDef-@tagDefinitions[i].tagDefinition.Guid"
- @bind=tagDefinitions[local].selected />
- <label
- for="tagDef-@tagDefinitions[i].tagDefinition.Guid"
- title=@title>
- @tagDefinitions[i].tagDefinition.Name
- </label>
-*@
- }
- </div>
+ @switch(state) {
+ case ComponentState.Loading:
+ <p><i>Loading...</i></p>
+ break;
+ case ComponentState.Error:
+ break;
+ case ComponentState.Loaded:
+ <input
+ type="text"
+ placeholder="Search"
+ autocorrect="off"
+ autocapitalize="off"
+ autocomplete="off"
+ @ref=queryInput
+ @oninput=QueryInput
+ @onkeypress=QueryKey
+ value=@query/>
+ <div class="tag-definitions">
+ @for(int i = 0; i < tagDefinitions.Count(); i++) {
+ if(!MatchesQuery(tagDefinitions[i].tagDefinition))
+ continue;
+ var local = i;
+ var ns = tagDefinitions[i].tagDefinition.Namespace;
+ var alias = tagDefinitions[i].tagDefinition.Alias;
+ var title = string.Join(" ", new[] {
+ ns,
+ alias is not null ? $"({alias})" : null
+ });
+ <input
+ type="checkbox"
+ id="tagDef-@tagDefinitions[i].tagDefinition.TagDefinitionId"
+ @bind=tagDefinitions[local].selected />
+ <label
+ for="tagDef-@tagDefinitions[i].tagDefinition.TagDefinitionId"
+ title=@title>
+ @tagDefinitions[i].tagDefinition.Name
+ </label>
+ }
+ </div>
+ break;
+ }
<ButtonContainer>
<button @onclick=@(() => dialog.Hide()) class="secondary">Cancel</button>
- <button @onclick=@(() => Submit())>Accept</button>
+ @if(state == ComponentState.Loaded) {
+ <button @onclick=@(() => Submit())>Accept</button>
+ }
</ButtonContainer>
</Dialog>
@@ -57,19 +65,21 @@
public EventCallback<TagDefinition[]> OnSubmit { get; set; }
public TagDefinition[] SelectedTags { get; set; } =
- Array.Empty<TagDefinition>();
+ Array.Empty<TagDefinition>();
public bool Visible {
get => visible;
set {
if(value)
- LoadTags();
+ LoadTagsAsync();
query = null;
visible = dialog.Visible = value;
}
}
- private (TagDefinition tagDefinition, bool selected)[] tagDefinitions;
+ private (TagDefinition tagDefinition, bool selected)[] tagDefinitions = [];
+
+ private ComponentState state = ComponentState.Loading;
// private HBContext db;
@@ -85,32 +95,39 @@
protected override void OnInitialized() {
// userService.UserSessionState.OnStateChange += ShowNsfwChanged;
- LoadTags();
+ LoadTagsAsync();
}
- private void LoadTags() {
+ private async void LoadTagsAsync() {
// db = dbFactory.CreateDbContext();
- // var selected = SelectedTags.Select(td => td.Guid);
+ var selected = SelectedTags.Select(td => td.TagDefinitionId);
+
+ // TODO: Factor in whether show NSFW is actually selected
+ bool showNsfw = true;
- // int[] nsfwTags = Array.Empty<int>();
+ Guid[] nsfwTags = Array.Empty<Guid>();
// if(!userService.UserSessionState.ShowNsfw)
// nsfwTags = tagService.TagsThatImply(HBContext.NsfwTag)
// .Select(td => td.ObjectId)
// .ToArray();
- // tagDefinitions = db.TagDefinitions
- // .Include(td => td.ImplicitTags)
- // .Where(td => td.Source == TagSource.UserTag)
- // .OrderBy(td => td.Name)
- // .AsEnumerable()
- // .Where(td => userService.UserSessionState.ShowNsfw || !td.ImplicitTags
- // .IntersectBy(nsfwTags, td => td.ObjectId)
- // .Any())
- // .Select(td => new Tuple<TagDefinition, bool>(
- // td,
- // selected.Contains(td.Guid)).ToValueTuple())
- // .ToArray();
+ try {
+ tagDefinitions = (await hb.Tag.GetTagDefinitionAsync())
+ // .Where(td => td.Source == TagSource.UserTag)
+ .OrderBy(td => td.Name)
+ .Where(td => showNsfw || !td.ImplicitTags.Intersect(nsfwTags).Any())
+ .Select(td => new Tuple<TagDefinition, bool>(
+ td,
+ selected.Contains(td.TagDefinitionId)).ToValueTuple())
+ .ToArray();
+
+ state = ComponentState.Loaded;
+ } catch {
+ state = ComponentState.Error;
+ }
+
+ await InvokeAsync(() => StateHasChanged());
}
private void QueryInput(ChangeEventArgs e) {
@@ -169,7 +186,7 @@
// return tagDef.Guid == singleTag.Guid;
// return tagDef.Name.ToLower().Contains(query.ToLower());
- return false;
+ return true;
}
private async void Submit() {
diff --git a/Pages/Component/Titlebar.razor b/Pages/Component/Titlebar.razor
index 521fb46..65af89a 100644
--- a/Pages/Component/Titlebar.razor
+++ b/Pages/Component/Titlebar.razor
@@ -51,8 +51,7 @@
<a class="desktop" href="/TagDefinitions">Tags</a>
<a class="desktop" href="/Gallery?ingest=true">Ingest</a>
<a class="desktop" href="/Upload">Upload</a>
- @* <a class="desktop" href="javascript:;" @onclick=@(() => aboutDialog.Show())>About</a> *@
- <a class="desktop" href="javascript:;">About</a>
+ <a class="desktop" href="javascript:;" @onclick=@(() => aboutDialog.Show())>About</a>
<p class="desktop" id="nsfw-label">NSFW</p>
<div id="nsfw-switch" class="desktop">
@@ -63,7 +62,7 @@
</form>
<a class="desktop" href="javascript:logout();">Logout</a>
</div>
- @* <AboutDialog @ref=aboutDialog/> *@
+ <AboutDialog @ref=aboutDialog/>
} else {
<div id="navbar">
<h2>Login</h2>
@@ -84,7 +83,7 @@
}
@code {
- // private AboutDialog aboutDialog;
+ private AboutDialog aboutDialog;
public string Username { get; set; } = "";
public string Password { get; set; } = "";
diff --git a/Pages/TagDefinitions.razor b/Pages/TagDefinitions.razor
index 7ce5400..b9f90d6 100644
--- a/Pages/TagDefinitions.razor
+++ b/Pages/TagDefinitions.razor
@@ -5,6 +5,7 @@
* @inject IUserService userService
* @implements IDisposable
*@
+@inject HBSession hb
<PageTitle>Tag Definitions</PageTitle>
@@ -24,28 +25,27 @@
<th></th>
</tr>
@foreach(var tagDef in tagDefinitions.Where(td => td.Namespace == ns)) {
- @* <tr data-guid="@tagDef.Guid"> *@
- <tr>
+ <tr data-guid="@tagDef.TagDefinitionId">
<td>@tagDef.Alias</td>
<td>
-@*
- <a href="/Gallery?t=@tagDef.Guid" class="nondecorated">
+ <a href="/Gallery?t=@tagDef.TagDefinitionId" class="nondecorated">
@tagDef.Name
</a>
-*@
</td>
<td>
<i>
@{
- // var implicitTags = tagDef.ImplicitTags
- // .Where(td => td.Source == TagSource.UserTag);
- // foreach(var tag in implicitTags) {
- // <a href="/Gallery?t=@tag.Guid" class="nondecorated">
- // @tag.Name
- // </a>
- // if(tag != implicitTags.Last())
- // @(", ")
- // }
+ var implicitTags = tagDefinitions
+ .IntersectBy(tagDef.ImplicitTags, td => td.TagDefinitionId)
+ .OrderBy(td => td.Name);
+ // .Where(td => td.Source == TagSource.UserTag);
+ foreach(var tag in implicitTags) {
+ <a href="/Gallery?t=@tag.TagDefinitionId" class="nondecorated">
+ @tag.Name
+ </a>
+ if(tag != implicitTags.Last())
+ @(", ")
+ }
}
</i>
</td>
@@ -97,37 +97,38 @@
private TagDefinition[] tagDefinitions;
- private string?[] tagNamespaces;
+ private string[] tagNamespaces = Array.Empty<string>();
// protected override void OnInitialized() =>
// userService.UserSessionState.OnStateChange += ShowNsfwChanged;
protected override void OnParametersSet() =>
- LoadTags();
+ LoadTagsAsync();
+
+ private async void LoadTagsAsync() {
+ bool showNsfw = true;
- private void LoadTags() {
- // int[] nsfwTags = Array.Empty<int>();
+ Guid[] nsfwTags = Array.Empty<Guid>();
// if(!userService.UserSessionState.ShowNsfw)
// nsfwTags = tagService.TagsThatImply(HBContext.NsfwTag)
// .Select(td => td.ObjectId)
// .ToArray();
- // tagDefinitions = dbFactory.CreateDbContext().TagDefinitions
- // .Include(td => td.ImplicitTags)
- // .Where(td => td.Source == TagSource.UserTag)
- // .OrderBy(td => td.Namespace)
- // .ThenBy(td => td.Name)
- // .AsEnumerable()
- // .Where(td => userService.UserSessionState.ShowNsfw || !td.ImplicitTags
- // .IntersectBy(nsfwTags, td => td.ObjectId)
- // .Any())
- // .ToArray();
+ tagDefinitions = (await hb.Tag.GetTagDefinitionAsync())
+ // TODO: Limit shown tags to user-tags
+ //.Where(td => td.Source == TagSource.UserTag)
+ .OrderBy(td => td.Namespace)
+ .ThenBy(td => td.Name)
+ .Where(td => showNsfw || !td.ImplicitTags.Intersect(nsfwTags).Any())
+ .ToArray();
+
+ tagNamespaces = tagDefinitions
+ .Select(td => td.Namespace)
+ .Order()
+ .Distinct()
+ .ToArray();
- // tagNamespaces = tagDefinitions
- // .Select(td => td.Namespace)
- // .Order()
- // .Distinct()
- // .ToArray();
+ await InvokeAsync(() => StateHasChanged());
}
private void PromptToDelete(TagDefinition toDelete) {
@@ -141,7 +142,7 @@
// tagService.DeleteTagDefinition(toDelete);
// deleteTagDialog.Hide();
- // LoadTags();
+ // LoadTagsAsync();
// StateHasChanged();
}
@@ -153,7 +154,7 @@
}
private void TagUpdated(object? sender, EventArgs e) {
- LoadTags();
+ LoadTagsAsync();
StateHasChanged();
}
@@ -169,7 +170,7 @@
return;
// tagService.SetImplicitTags(toEditImplicit, tagDefs);
- LoadTags();
+ LoadTagsAsync();
StateHasChanged();
}
@@ -178,13 +179,13 @@
// tagService.AddImplicitTag(tagDef.Guid, HBContext.NsfwTag);
// else
// tagService.RemoveImplicitTag(tagDef.Guid, HBContext.NsfwTag);
- // LoadTags();
+ // LoadTagsAsync();
// StateHasChanged();
}
// private async void ShowNsfwChanged(UserSessionState userSessionState) =>
// await InvokeAsync(() => {
- // LoadTags();
+ // LoadTagsAsync();
// StateHasChanged();
// });
diff --git a/Pages/ViewMedia.razor b/Pages/ViewMedia.razor
index e210e79..d44b430 100644
--- a/Pages/ViewMedia.razor
+++ b/Pages/ViewMedia.razor
@@ -1,9 +1,9 @@
@page "/ViewMedia"
-@* @using HyperBooru.Util*@
+@inject ISourceService sourceService
@inject HBSession hb
@inject IJSRuntime jsRuntime
-<PageTitle>@title</PageTitle>
+<PageTitle>@Title</PageTitle>
<script suppress-warning="BL9992">
function toggleSidebar() {
@@ -62,8 +62,7 @@
<p>Title: <i>@(media?.ShortDescription ?? "None")</i></p>
<p class="newlines">Description:<br/><i>@(media?.LongDescription ?? "None")</i></p>
}
-@*
- <p>Resolution: @(media.CurrentUploadedFile.Width)x@(media.CurrentUploadedFile.Height)</p>
+ @*<p>Resolution: @(media.CurrentUploadedFile.Width)x@(media.CurrentUploadedFile.Height)</p>*@
<p class="heading">Upload history</p>
<hr/>
<table id="uploaded-files" class="data-table">
@@ -75,36 +74,45 @@
<th>Size</th>
<th>Original Checksum</th>
</tr>
- @foreach(var file in media.UploadedFiles.OrderByDescending(uf => uf.UploadTime)) {
- string? sourceUrl = null;
- if(file.Filename is not null)
- sourceUrl = sourceService.GetUrlFromFilename(file.Filename);
- <tr>
- <td title=@file.CreateTime?.ToString()>
- @(file.CreateTime?.ToString("d") ?? "N/A")
- </td>
- <td title=@file.LastWriteTime?.ToString()>
- @(file.LastWriteTime?.ToString("d") ?? "N/A")
- </td>
- <td title=@file.UploadTime>@(file.UploadTime.ToString("d"))</td>
- <td title=@(file.Path is not null ? $"{file.Path.Replace('\\', '/')}/{file.Filename}" : file.Filename)>
- @if(sourceUrl is not null) {
- <a class="nondecorated" target="_blank" href=@sourceUrl>@file.Filename</a>
- } else {
- @file.Filename
- }
- </td>
- <td title=@file.Length>@file.Length.ToBytesSI()</td>
- <td
- title=@(file.Checksum + (file.ChecksumVerified ? " (verified)" : ""))
- class=@(file.ChecksumVerified ? "verified" : null)>
-
- @file.Checksum.Substring(0, 8)
- </td>
- </tr>
- }
+ <LoadableContent T="List<UploadedFile>" DataSource=LoadUploadedFiles @ref=uploadedFilesContent>
+ <LoadingState>
+ <p><i>Loading...</i></p>
+ </LoadingState>
+ <ErrorState>
+ <p><i>Unable to fetch file info for this item!</i></p>
+ </ErrorState>
+ <LoadedState>
+ @foreach(var file in uploadedFilesContent.Data!) {
+ string? sourceUrl = null;
+ if(file.Filename is not null)
+ sourceUrl = sourceService.GetUrlFromFilename(file.Filename);
+ <tr>
+ <td title=@file.CreateTime?.ToString()>
+ @(file.CreateTime?.ToString("d") ?? "N/A")
+ </td>
+ <td title=@file.LastWriteTime?.ToString()>
+ @(file.LastWriteTime?.ToString("d") ?? "N/A")
+ </td>
+ <td title=@file.UploadTime>@(file.UploadTime.ToString("d"))</td>
+ <td title=@(file.Path is not null ? $"{file.Path.Replace('\\', '/')}/{file.Filename}" : file.Filename)>
+ @if(sourceUrl is not null) {
+ <a class="nondecorated" target="_blank" href=@sourceUrl>@file.Filename</a>
+ } else {
+ @file.Filename
+ }
+ </td>
+ <td title=@file.Length>@file.Length.ToBytesSI()</td>
+ <td
+ title=@(file.Checksum + (file.ChecksumVerified ? " (verified)" : ""))
+ class=@(file.ChecksumVerified ? "verified" : null)>
+
+ @file.Checksum.Substring(0, 8)
+ </td>
+ </tr>
+ }
+ </LoadedState>
+ </LoadableContent>
</table>
-*@
</div>
<div id="metadata-tags">
<p class="heading">Tags</p>
@@ -114,8 +122,7 @@
</div>
<div id="button-container">
<ButtonContainer>
-@*
- <button @onclick=@(() => deleteDialog.Show()) class="warning" data-keyboard-shortcut="d">
+ <button @onclick=@(() => deleteDialog.Show()) class="warning" data-keyboard-shortcut="d">
<img src="/images/trash.svg"/>
<p><u>D</u>elete</p>
</button>
@@ -127,7 +134,6 @@
<img src="/images/book.svg"/>
<p>View <u>O</u>CR</p>
</button>
-*@
@if(infoEditMode) {
@*
<button @onclick=@(() => ApplyInfoEdit(false)) class="secondary">
@@ -168,7 +174,6 @@
</div>
</div>
-@*
<Dialog Title="Delete this media?" @ref=deleteDialog>
<ButtonContainer>
<button @onclick=@(() => deleteDialog.Hide()) class="secondary">Cancel</button>
@@ -177,11 +182,13 @@
</Dialog>
<Dialog Title="OCR Data" @ref=ocrDialog>
- @if(media.OcrData is null) {
+ @*@if(media.OcrData is null) {*@
<p><center>This media item hasn't been scanned yet!</center></p>
+@*
} else {
<code style="max-height:400px;">@media.OcrData?.Text</code>
}
+*@
<ButtonContainer>
<button @onclick=@(() => ocrDialog.Hide())>Close</button>
</ButtonContainer>
@@ -191,14 +198,15 @@
Title="Select one or more tag(s) to add"
OnSubmit=AddTags
@ref=tagDialog/>
-*@
@code {
[Parameter]
[SupplyParameterFromQuery(Name = "m")]
public Guid MediaId { get; set; }
- private ApiModels.Media media;
+ private ApiModels.Media? media;
+
+ private LoadableContent<List<UploadedFile>> uploadedFilesContent;
private string title;
@@ -207,9 +215,9 @@
private string? longDescription;
private MediaTagTable mediaTagTable;
- // private Dialog deleteDialog;
- // private Dialog ocrDialog;
- // private TagSelectDialog tagDialog;
+ private Dialog deleteDialog;
+ private Dialog ocrDialog;
+ private TagSelectDialog tagDialog;
private ElementReference shortDescriptionInput;
@@ -223,24 +231,20 @@
private async void LoadMedia() {
media = await hb.Media.GetAsync(MediaId);
- // using var db = dbFactory.CreateDbContext();
- // media = db.Media
- // .Include(m => m.Tags)
- // .ThenInclude(t => t.TagDefinition)
- // .Include(m => m.CurrentUploadedFile)
- // .Include(m => m.UploadedFiles)
- // .Include(m => m.OcrData)
- // .First(m => m.Guid == MediaId);
+ await InvokeAsync(() => StateHasChanged());
+ }
- // title = media.DisplayName ?? "Media View";
- // InvokeAsync(() => StateHasChanged());
+ private async Task<List<UploadedFile>> LoadUploadedFiles() {
+ return (await hb.Media.GetUploadedFilesAsync(MediaId))
+ .OrderByDescending(uf => uf.UploadTime)
+ .ToList();
}
- // private void AddTags(TagDefinition[] tagDefs) {
- // foreach(var tagDef in tagDefs)
- // tagService.AddTag(media, tagDef);
- // mediaTagTable.Refresh();
- // }
+ private void AddTags(TagDefinition[] tagDefs) {
+ // foreach(var tagDef in tagDefs)
+ // tagService.AddTag(media, tagDef);
+ // mediaTagTable.Refresh();
+ }
private async void SetIngest(bool ingest) {
// mediaService.SetIngest(media, ingest);
@@ -252,6 +256,23 @@
await jsRuntime.InvokeVoidAsync("history.back");
}
+ private string Title {
+ get {
+ if(media is null)
+ return "View Media";
+
+ if(media.ShortDescription is not null)
+ return media.ShortDescription;
+
+ if(uploadedFilesContent.Data is null)
+ return $"Media ({media.MediaId.ToString().ToUpper().Substring(0, 8)})";
+
+ return uploadedFilesContent.Data
+ .OrderBy(f => f.UploadTime)
+ .FirstOrDefault()?.Filename ?? media.MediaId.ToString().ToUpper();
+ }
+ }
+
private bool InfoEditMode {
get => infoEditMode;
set {
@@ -271,8 +292,8 @@
// infoEditMode = false;
// }
- // private async void DeleteMedia() {
- // mediaService.Delete(media);
- // await jsRuntime.InvokeVoidAsync("history.back");
- // }
+ private async void DeleteMedia() {
+ // mediaService.Delete(media);
+ // await jsRuntime.InvokeVoidAsync("history.back");
+ }
}