diff options
Diffstat (limited to 'Pages/ViewMedia.razor')
| -rw-r--r-- | Pages/ViewMedia.razor | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/Pages/ViewMedia.razor b/Pages/ViewMedia.razor new file mode 100644 index 0000000..ce9d608 --- /dev/null +++ b/Pages/ViewMedia.razor @@ -0,0 +1,218 @@ +@page "/ViewMedia" +@using HyperBooru.Util +@inject IJSRuntime jsRuntime +@inject IDbContextFactory<HBContext> dbFactory +@inject ITagService tagService +@inject IMediaService mediaService +@inject ISourceService sourceService +@attribute [Authorize] + +<PageTitle>@title</PageTitle> + +<script suppress-warning="BL9992"> + function toggleSidebar() { + document.getElementById("metadata").classList.toggle("hidden"); + } +</script> + +<div id="content"> + <div id="image-container"> + <img + src="/media/@(media.Guid)" + width=@media.CurrentUploadedFile.Width + height=@media.CurrentUploadedFile.Height + onclick="toggleSidebar()"/> + </div> + <div id="metadata"> + <div id="metadata-container"> + <div id="metadata-fileinfo"> + @if(infoEditMode) { + <form action="javascript:;" @onsubmit=@(() => ApplyInfoEdit(true))> + <table id="edit-metadata"> + <tr> + <td>Title:</td> + <td><input type="text" @bind=shortDescription @ref=shortDescriptionInput/></td> + </tr> + <tr> + <td>Description:</td> + <td><textarea rows="4" @bind=longDescription/></td> + </tr> + </table> + </form> + } else { + <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 class="heading">Upload history</p> + <hr/> + <table id="uploaded-files" class="data-table"> + <tr> + <th>Created On</th> + <th>Last Write</th> + <th>Uploaded On</th> + <th>Filename</th> + <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.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> + } + </table> + </div> + <div id="metadata-tags"> + <p class="heading">Tags</p> + <hr/> + <MediaTagTable Media=media @ref=mediaTagTable/> + </div> + </div> + <div id="button-container"> + <ButtonContainer> + <button @onclick=@(() => deleteDialog.Show()) class="warning" data-keyboard-shortcut="d"><u>D</u>elete</button> + <button @onclick=@(() => tagDialog.Show()) class="secondary" data-keyboard-shortcut="t">Add <u>T</u>ag</button> + <button @onclick=@(() => ocrDialog.Show()) class="secondary" data-keyboard-shortcut="o">View <u>O</u>CR</button> + @if(infoEditMode) { + <button @onclick=@(() => ApplyInfoEdit(false)) class="secondary">Cancel</button> + <button @onclick=@(() => ApplyInfoEdit(true))>Apply</button> + } else { + <button @onclick=@(() => InfoEditMode = true) class="secondary" data-keyboard-shortcut="e"><u>E</u>dit Info</button> + } + @if(media.IsIngest) { + <button @onclick=@(() => SetIngest(false)) data-keyboard-shortcut="c">Mark Tagging <u>C</u>omplete</button> + } else { + <button class="secondary" @onclick=@(() => SetIngest(true)) data-keyboard-shortcut="c">Mark Tagging In<u>c</u>omplete</button> + } + </ButtonContainer> + </div> + </div> +</div> + +<Dialog Title="Delete this media?" @ref=deleteDialog> + <ButtonContainer> + <button @onclick=@(() => deleteDialog.Hide()) class="secondary">Cancel</button> + <button @onclick=DeleteMedia class="warning">Confirm</button> + </ButtonContainer> +</Dialog> + +<Dialog Title="OCR Data" @ref=ocrDialog> + @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> +</Dialog> + +<TagSelectDialog + Title="Select one or more tag(s) to add" + OnSubmit=AddTags + @ref=tagDialog/> + +@code { + [Parameter] + [SupplyParameterFromQuery(Name = "m")] + public Guid MediaId { get; set; } + + private Media media; + + private string title; + + private bool infoEditMode = false; + private string? shortDescription; + private string? longDescription; + + private MediaTagTable mediaTagTable; + private Dialog deleteDialog; + private Dialog ocrDialog; + private TagSelectDialog tagDialog; + + private ElementReference shortDescriptionInput; + + protected override void OnInitialized() => + LoadMedia(); + + protected override async void OnAfterRender(bool firstRender) { + if(infoEditMode) + await shortDescriptionInput.FocusAsync(); + } + + private void LoadMedia() { + 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); + + title = media.DisplayName ?? "Media View"; + } + + 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); + LoadMedia(); + + if(ingest) + StateHasChanged(); + else + await jsRuntime.InvokeVoidAsync("history.back"); + } + + private bool InfoEditMode { + get => infoEditMode; + set { + shortDescription = media.ShortDescription; + longDescription = media.LongDescription; + infoEditMode = value; + StateHasChanged(); + } + } + + private void ApplyInfoEdit(bool apply) { + if(apply) { + mediaService.SetDescription(media, shortDescription, longDescription); + LoadMedia(); + } + + infoEditMode = false; + } + + private async void DeleteMedia() { + mediaService.Delete(media); + await jsRuntime.InvokeVoidAsync("history.back"); + } +} |
