summaryrefslogtreecommitdiff
path: root/Pages
diff options
context:
space:
mode:
authorJake Mannens <jake@asger.xyz>2023-08-11 00:59:50 +1000
committerJake Mannens <jake@asger.xyz>2023-08-11 00:59:50 +1000
commit1e81791d10271c3e3828a92a01a3aba6a74f9ba8 (patch)
tree3246a49440f24c1e1f04691bdfbb2f52229045cf /Pages
parente210a6e4e973adc5d873657ea742ad0d8efd96ae (diff)
Added ability to tag media
Diffstat (limited to 'Pages')
-rw-r--r--Pages/Shared/_Layout.cshtml.css2
-rw-r--r--Pages/TagDefinitions.cshtml12
-rw-r--r--Pages/TagDefinitions.cshtml.css4
-rw-r--r--Pages/ViewMedia.cshtml59
-rw-r--r--Pages/ViewMedia.cshtml.cs3
-rw-r--r--Pages/ViewMedia.cshtml.css38
6 files changed, 100 insertions, 18 deletions
diff --git a/Pages/Shared/_Layout.cshtml.css b/Pages/Shared/_Layout.cshtml.css
index 337ec17..22e36db 100644
--- a/Pages/Shared/_Layout.cshtml.css
+++ b/Pages/Shared/_Layout.cshtml.css
@@ -4,12 +4,14 @@
}
div#navbar > a {
+ color: white;
display: inline-block;
padding: 20px 20px 20px 20px;
}
div#navbar > a:hover {
background: rgba(255, 255, 255, 0.4);
+ filter: none;
}
div#navbar > a:active {
diff --git a/Pages/TagDefinitions.cshtml b/Pages/TagDefinitions.cshtml
index a05f5d5..7bf1790 100644
--- a/Pages/TagDefinitions.cshtml
+++ b/Pages/TagDefinitions.cshtml
@@ -27,7 +27,9 @@
async function deleteTagDefinition() {
var dialog = document.getElementById('delete-dialog');
- var resp = await fetch(`/api/tag/def/${dialog.dataset.guid}`, {
+ var tagDefId = dialog.dataset.guid;
+
+ var resp = await fetch(`/api/tag/def/${tagDefId}`, {
method: 'delete'
});
@@ -35,7 +37,9 @@
alert('Error deleting tag definition!');
showDeleteDialog(false);
} else {
- window.location.reload()
+ var rows = Array.from(document.getElementsByTagName('tr'));
+ rows.find(r => r.dataset.guid == tagDefId).remove();
+ showDeleteDialog(false);
}
}
@@ -65,12 +69,12 @@
<th></th>
</tr>
@foreach(var tagDef in Model.TagDefinitions) {
- <tr>
+ <tr data-guid="@tagDef.Guid">
<td>@tagDef.Guid</td>
<td>@tagDef.Source</td>
<td>@tagDef.Namespace</td>
<td>@tagDef.Name</td>
- <td><button onclick="showDeleteDialog('@tagDef.Guid')">Delete</button></td>
+ <td><a href="javascript:showDeleteDialog('@tagDef.Guid');">Delete</a></td>
</tr>
}
</table>
diff --git a/Pages/TagDefinitions.cshtml.css b/Pages/TagDefinitions.cshtml.css
index 0a9e226..93001c7 100644
--- a/Pages/TagDefinitions.cshtml.css
+++ b/Pages/TagDefinitions.cshtml.css
@@ -9,8 +9,4 @@ div.button-container {
table#tag-definitions td:first-child {
font-family: 'Lucida Console';
-}
-
-table#tag-definitions td > button {
- margin-top: 0;
} \ No newline at end of file
diff --git a/Pages/ViewMedia.cshtml b/Pages/ViewMedia.cshtml
index 0bf58cd..e37bbf1 100644
--- a/Pages/ViewMedia.cshtml
+++ b/Pages/ViewMedia.cshtml
@@ -7,8 +7,9 @@
<link rel="stylesheet" type="text/css" href="@(nameof(HyperBooru)).styles.css"/>
<script>
+ var mediaId = new URL(window.location.href).searchParams.get('m');
+
async function deleteMedia() {
- var mediaId = new URL(window.location.href).searchParams.get('m');
var resp = await fetch('/media/' + mediaId, { method: 'delete' });
if(resp.ok) {
window.location.href = '/';
@@ -17,12 +18,42 @@
}
}
+ async function applyTags() {
+ var checkboxes = Array.from(document
+ .getElementById('tag-definitions')
+ .getElementsByTagName('input'));
+
+ var tagDefIds = checkboxes
+ .filter(cb => cb.checked)
+ .map(cb => cb.id.replace(/^tagdef-/, ''));
+
+ var pendingRequests = tagDefIds
+ .map(id => fetch(`/api/tag/${mediaId}/${id}`, { method: 'POST' }));
+
+ var responses = await Promise.all(pendingRequests);
+
+ if(responses.some(r => !r.ok && r.status != 400)) {
+ alert('Error setting tags!');
+ }
+ showTagDialog(false);
+ }
+
+ async function removeTag(e, tagDefId) {
+ var resp = await fetch(`/api/tag/${mediaId}/${tagDefId}`, { method: 'DELETE' });
+ if(!resp.ok && resp.status != 400) {
+ alert('Error removing tag!');
+ } else {
+ e.closest('tr').remove();
+ }
+ }
+
function showDeleteDialog(visible) {
document.getElementById('delete-dialog').classList.toggle('visible', visible);
}
function showTagDialog(visible) {
document.getElementById('tag-dialog').classList.toggle('visible', visible);
+ document.querySelector('div#tag-dialog input').focus();
}
function selectPane(tab) {
@@ -90,8 +121,19 @@
<div id="metadata-tags">
<table class="data-table">
<tr>
+ <th>Source</th>
+ <th>Namespace</th>
<th>Tag Name</th>
+ <th></th>
</tr>
+ @foreach(var tag in Model.Media.Tags.Select(t => t.TagDefinition)) {
+ <tr>
+ <td>@tag.Source</td>
+ <td>@tag.Namespace</td>
+ <td>@tag.Name</td>
+ <td><a href="javascript:;" onclick="removeTag(this, '@tag.Guid')">Delete</a></td>
+ </tr>
+ }
</table>
<div class="button-container">
<button onclick="showTagDialog(true)">Add Tag</button>
@@ -109,19 +151,18 @@
</div>
</div>
-<div id="tag-dialog" class="dialog visible">
+<div id="tag-dialog" class="dialog">
<p>Select one or more tag(s) to add</p>
<hr/>
<input type="text" placeholder="Search"/>
- <table>
- @for(int i = 0; i < 7; i++) {
- <tr>
- <td>@i</td>
- </tr>
+ <div id="tag-definitions">
+ @foreach(var tagdef in Model.TagDefinitions) {
+ <input type="checkbox" id="tagdef-@tagdef.Guid"/>
+ <label for="tagdef-@tagdef.Guid">@tagdef.Name</label>
}
- </table>
+ </div>
<div class="button-container">
<button onclick="showTagDialog(false)" class="secondary">Cancel</button>
- <button>Accept</button>
+ <button onclick="applyTags()">Accept</button>
</div>
</div>
diff --git a/Pages/ViewMedia.cshtml.cs b/Pages/ViewMedia.cshtml.cs
index fe8d150..476ea40 100644
--- a/Pages/ViewMedia.cshtml.cs
+++ b/Pages/ViewMedia.cshtml.cs
@@ -6,6 +6,9 @@ namespace HyperBooru.Pages;
public class ViewMediaModel : PageModel {
public DbMedia Media { get; private set; }
+ public IEnumerable<DbTagDefinition> TagDefinitions =>
+ db.TagDefinitions;
+
private HyperBooruDbContext db;
public ViewMediaModel(HyperBooruDbContext db) =>
diff --git a/Pages/ViewMedia.cshtml.css b/Pages/ViewMedia.cshtml.css
index b173266..f51e18f 100644
--- a/Pages/ViewMedia.cshtml.css
+++ b/Pages/ViewMedia.cshtml.css
@@ -37,6 +37,7 @@ div#metadata-header > a.selected {
div#metadata-header > a:hover {
background: rgba(255, 255, 255, 0.4);
+ filter: none;
}
div#metadata-fileinfo > table th {
@@ -48,7 +49,42 @@ div#metadata-fileinfo > table td {
font-size: 8pt;
}
+div#metadata-tags > table td {
+ font-size: 8pt;
+}
+
div.button-container {
display: flex;
justify-content: flex-end;
-} \ No newline at end of file
+}
+
+div#tag-dialog {
+ max-height: 400px;
+}
+
+div#tag-dialog div#tag-definitions {
+ overflow-y: auto;
+ user-select: none;
+}
+
+div#tag-dialog div#tag-definitions label {
+ background: #555;
+ border-radius: 10px;
+ display: inline-block;
+ font-size: 10pt;
+ margin: 0 5px 5px 0;
+ padding: 5px 7px 5px 7px;
+ transition: background 0.1s linear;
+}
+
+div#tag-dialog div#tag-definitions label:hover {
+ background: #777;
+}
+
+div#tag-dialog div#tag-definitions input:checked + label {
+ background: #aaa;
+}
+
+div#tag-dialog div#tag-definitions input {
+ display: none;
+}