summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJake Mannens <jake@asger.xyz>2023-08-17 04:38:03 +1000
committerJake Mannens <jake@asger.xyz>2025-08-18 17:03:21 +1000
commit5d462af49365e84e0dfd7ed5bd862efb6b325cd1 (patch)
treebdb2fbd894916ad0cdb5ce64fa68fdab9d2d8130
parentcfa09334407e962f57ba4aca7905265d22424c33 (diff)
Added UI to set implicit tags
-rw-r--r--MainLayout.razor20
-rw-r--r--Pages/Component/MediaTagTable.razor43
-rw-r--r--Pages/Component/TagSelectDialog.razor25
-rw-r--r--Pages/Index.razor2
-rw-r--r--Pages/TagDefinitions.razor44
-rw-r--r--Server.csproj4
-rw-r--r--Services/TagService.cs26
7 files changed, 102 insertions, 62 deletions
diff --git a/MainLayout.razor b/MainLayout.razor
index b34bf64..bd0675b 100644
--- a/MainLayout.razor
+++ b/MainLayout.razor
@@ -2,14 +2,12 @@
<link href="@(nameof(HyperBooru)).styles.css" rel="stylesheet" />
-<main>
- <div id="navbar">
- <a href="/">Home</a>
- <a href="/TagDefinitions">Tags</a>
- <input type="text" placeholder="Search"/>
- </div>
- @* <div id="content" style="overflow-y:@(ViewBag.ContentScroll ? "auto" : "hidden");padding:@(ViewBag.ContentMargin ?? "0");"> *@
- <div id="content">
- @Body
- </div>
-</main>
+<div id="navbar">
+ <a href="/">Home</a>
+ <a href="/TagDefinitions">Tags</a>
+ <input type="text" placeholder="Search"/>
+</div>
+@* <div id="content" style="overflow-y:@(ViewBag.ContentScroll ? "auto" : "hidden");padding:@(ViewBag.ContentMargin ?? "0");"> *@
+<div id="content">
+ @Body
+</div>
diff --git a/Pages/Component/MediaTagTable.razor b/Pages/Component/MediaTagTable.razor
index d4a4283..278304d 100644
--- a/Pages/Component/MediaTagTable.razor
+++ b/Pages/Component/MediaTagTable.razor
@@ -9,25 +9,25 @@
<th>Tag Name</th>
<th></th>
</tr>
- @foreach(var tagDef in tagDefs) {
+ @foreach(var e in tagDefs) {
<tr>
<td>
- @if(implicitTags[tagDef.Guid]) {
- <i>@tagDef.Namespace</i>
+ @if(e.isImplicit) {
+ <i>@e.tagDef.Namespace</i>
} else {
- @tagDef.Namespace
+ @e.tagDef.Namespace
}
</td>
<td>
- @if(implicitTags[tagDef.Guid]) {
- <i>@tagDef.Name</i>
+ @if(e.isImplicit) {
+ <i>@e.tagDef.Name</i>
} else {
- @tagDef.Name
+ @e.tagDef.Name
}
</td>
<td>
- @if(!implicitTags[tagDef.Guid]) {
- <a href="javascript:;" @onclick=@(() => Delete(tagDef))>Delete</a>
+ @if(!e.isImplicit) {
+ <a href="javascript:;" @onclick=@(() => Delete(e.tagDef))>Delete</a>
}
</td>
</tr>
@@ -38,8 +38,7 @@
[Parameter]
public Media Media { get; set; }
- private TagDefinition[] tagDefs;
- private Dictionary<Guid, bool> implicitTags;
+ private (TagDefinition tagDef, bool isImplicit)[] tagDefs;
protected override void OnInitialized() => LoadTagDefs();
@@ -57,22 +56,8 @@
using var db = dbFactory.CreateDbContext();
var media = db.Media.First(m => m.ObjectId == Media.ObjectId);
- tagDefs = GetTagRecursive(
- media.Tags
- .Select(t => t.TagDefinition))
- .Where(td => td.Source == TagSource.UserTag)
- .OrderBy(td => td.Namespace)
- .ThenBy(td => td.Name)
- .ToArray();
-
- implicitTags = new(tagDefs
- .Select(td => new KeyValuePair<Guid, bool>(
- td.Guid,
- !media.Tags.Select(t => t.TagDefinition.Guid).Contains(td.Guid))));
-}
-
- private IEnumerable<TagDefinition> GetTagRecursive(IEnumerable<TagDefinition> tagDefs) =>
- tagDefs
- .Concat(tagDefs.SelectMany(td => GetTagRecursive(td.ImplicitTags)))
- .DistinctBy(td => td.Guid);
+ tagDefs = tagService.GetAllTags(Media)
+ .Where(e => e.tagDefinition.Source == TagSource.UserTag)
+ .ToArray();
+ }
}
diff --git a/Pages/Component/TagSelectDialog.razor b/Pages/Component/TagSelectDialog.razor
index b8ff1d1..699ca3a 100644
--- a/Pages/Component/TagSelectDialog.razor
+++ b/Pages/Component/TagSelectDialog.razor
@@ -38,9 +38,16 @@
[Parameter]
public EventCallback<TagDefinition[]> OnSubmit { get; set; }
+ public TagDefinition[] SelectedTags { get; set; } =
+ Array.Empty<TagDefinition>();
+
public bool Visible {
get => visible;
- set => visible = dialog.Visible = value;
+ set {
+ if(value)
+ LoadTags();
+ visible = dialog.Visible = value;
+ }
}
private (TagDefinition tagDefinition, bool selected)[] tagDefinitions;
@@ -54,18 +61,28 @@
public void Show() => Visible = true;
public void Hide() => Visible = false;
- protected override void OnInitialized() {
+ protected override void OnInitialized() => LoadTags();
+
+ private void LoadTags() {
db = dbFactory.CreateDbContext();
+
+ var selected = SelectedTags.Select(td => td.Guid);
+
tagDefinitions = db.TagDefinitions
.Where(td => td.Source == TagSource.UserTag)
.OrderBy(td => td.Name)
- .Select(td => new Tuple<TagDefinition, bool>(td, false).ToValueTuple())
+ .Select(td => new Tuple<TagDefinition, bool>(
+ td,
+ selected.Contains(td.Guid)).ToValueTuple())
.ToArray();
}
private async void Submit() {
await OnSubmit.InvokeAsync(
- tagDefinitions.Select(e => e.tagDefinition).ToArray());
+ tagDefinitions
+ .Where(e => e.selected)
+ .Select(e => e.tagDefinition)
+ .ToArray());
for(int i = 0; i < tagDefinitions.Count(); i++)
tagDefinitions[i].selected = false;
Hide();
diff --git a/Pages/Index.razor b/Pages/Index.razor
index a69d69c..4719530 100644
--- a/Pages/Index.razor
+++ b/Pages/Index.razor
@@ -10,7 +10,7 @@
<input type="submit" />
</form>
-@foreach(var media in db.Media) {
+@foreach(var media in db.Media.OrderByDescending(m => m.ObjectId)) {
<a href="/ViewMedia?m=@(media.Guid)">
<img src="/media/thumb/@(media.Guid)?h=200" />
</a>
diff --git a/Pages/TagDefinitions.razor b/Pages/TagDefinitions.razor
index b28ef0c..75e93f9 100644
--- a/Pages/TagDefinitions.razor
+++ b/Pages/TagDefinitions.razor
@@ -8,23 +8,27 @@
<table id="tag-definitions" class="data-table">
<tr>
- <th>Source</th>
<th>Namespace</th>
<th>Name</th>
<th>Implicit Tags</th>
<th></th>
</tr>
@foreach(var tagDef in tagDefinitions) {
- TagSourceMap.TryGetValue(tagDef.Source, out var source);
<tr data-guid="@tagDef.Guid">
- <td>@(source ?? tagDef.Source.ToString())</td>
<td>@tagDef.Namespace</td>
<td>@tagDef.Name</td>
- <td></td>
<td>
- <a href="javascript:showDeleteDialog('@tagDef.Guid');" @onclick=@(() => PromptToDelete(tagDef))>
+ <i>
+ @(string.Join(", ", tagDef.ImplicitTags.Select(it => it.Name).Order()))
+ </i>
+ </td>
+ <td>
+ <a href="javascript:;" @onclick=@(() => PromptToDelete(tagDef))>
Delete
</a>
+ <a href="javascript:;" @onclick=@(() => PromptImplicitTags(tagDef))>
+ Implicit Tags
+ </a>
</td>
</tr>
}
@@ -54,18 +58,20 @@
</div>
</Dialog>
+<TagSelectDialog
+ OnSubmit=SetImplicitTags
+ @ref=implicitTagDialog />
+
@code {
- private readonly Dictionary<TagSource, string> TagSourceMap = new() {
- { TagSource.UserTag, "User" }
- };
-
- private Dialog createTagDialog;
- private Dialog deleteTagDialog;
+ private Dialog createTagDialog;
+ private Dialog deleteTagDialog;
+ private TagSelectDialog implicitTagDialog;
private string tagName;
private string? tagNamespace;
private TagDefinition? toDelete;
+ private TagDefinition? toEditImplicit;
private IEnumerable<TagDefinition> tagDefinitions =>
dbFactory.CreateDbContext().TagDefinitions
@@ -94,4 +100,20 @@
tagService.DeleteTagDefinition(toDelete);
deleteTagDialog.Hide();
}
+
+ private void PromptImplicitTags(TagDefinition toEditImplicit) {
+ this.toEditImplicit = toEditImplicit;
+ implicitTagDialog.SelectedTags =
+ toEditImplicit.ImplicitTags.ToArray();
+ implicitTagDialog.Show();
+ }
+
+ private void SetImplicitTags(TagDefinition[] tagDefs) {
+ if(toEditImplicit is null)
+ return;
+
+ foreach(var tagDef in tagDefs)
+ tagService.AddImplicitTag(toEditImplicit, tagDef);
+ StateHasChanged();
+ }
}
diff --git a/Server.csproj b/Server.csproj
index 5eb5f1d..10953e6 100644
--- a/Server.csproj
+++ b/Server.csproj
@@ -32,8 +32,4 @@
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
</ItemGroup>
- <ItemGroup>
- <Folder Include="Data\" />
- </ItemGroup>
-
</Project>
diff --git a/Services/TagService.cs b/Services/TagService.cs
index e0d1072..da2bb2d 100644
--- a/Services/TagService.cs
+++ b/Services/TagService.cs
@@ -1,4 +1,5 @@
-using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Components.Web;
+using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace HyperBooru.Services;
@@ -12,6 +13,8 @@ public interface ITagService {
public void RemoveImplicitTag(TagDefinition tagDef, TagDefinition implicitTagDef);
public void CreateTagDefinition(string name, string? @namespace);
public void DeleteTagDefinition(TagDefinition tagDef);
+ public (TagDefinition tagDefinition, bool isImplicit)[] GetAllTags(Guid obj);
+ public (TagDefinition tagDefinition, bool isImplicit)[] GetAllTags(HBObject obj);
}
public class TagService : ITagService {
@@ -97,4 +100,23 @@ public class TagService : ITagService {
transaction.Commit();
}
-} \ No newline at end of file
+
+ public (TagDefinition tagDefinition, bool isImplicit)[] GetAllTags(Guid obj) {
+ IEnumerable<TagDefinition> GetTagRecursive(IEnumerable<TagDefinition> tagDefs) =>
+ tagDefs
+ .Concat(tagDefs.SelectMany(td => GetTagRecursive(td.ImplicitTags)))
+ .DistinctBy(td => td.Guid);
+
+ using var db = dbFactory.CreateDbContext();
+ var @object = db.Objects.First(o => o.Guid == obj);
+
+ var guids = @object.Tags.Select(t => t.TagDefinition.Guid);
+
+ return GetTagRecursive(@object.Tags.Select(t => t.TagDefinition))
+ .Select(td => new ValueTuple<TagDefinition, bool>(td, !guids.Contains(td.Guid)))
+ .ToArray();
+ }
+
+ public (TagDefinition tagDefinition, bool isImplicit)[] GetAllTags(HBObject obj) =>
+ GetAllTags(obj.Guid);
+}