summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--wwwroot/styles/global.css56
7 files changed, 147 insertions, 27 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;
+}
diff --git a/wwwroot/styles/global.css b/wwwroot/styles/global.css
index 3ce0533..969c531 100644
--- a/wwwroot/styles/global.css
+++ b/wwwroot/styles/global.css
@@ -1,10 +1,15 @@
:root {
- --col-accent-pri: #0aa;
- --col-bg: #222;
- --col-dialog-bg: #333;
- --col-navbar-bg: var(--col-accent-pri);
- --col-button-pri: var(--col-accent-pri);
- --col-button-sec: #555;
+ --col-accent-pri: #0aa;
+ --col-accent-pri-hl: #0cc;
+ --col-bg: #222;
+ --col-dialog-bg: #333;
+ --col-navbar-bg: var(--col-accent-pri);
+ --col-button-pri: var(--col-accent-pri);
+ --col-button-pri-hl: var(--col-accent-pri-hl);
+ --col-button-sec: #555;
+ --col-button-sec-hl: #777;
+ --col-scrollbar: #666666;
+ --col-scrollbar-hover: #aaaaaa;
}
body {
@@ -18,10 +23,14 @@ body {
}
a {
- color: white;
+ color: var(--col-accent-pri);
text-decoration: none;
}
+a:hover {
+ filter: brightness(1.5);
+}
+
button, input[type=submit] {
color: white;
background: var(--col-button-pri);
@@ -31,18 +40,29 @@ button, input[type=submit] {
height: 30px;
margin: 10px 5px 0 5px;
padding: 0 9px 0 9px;
+ user-select: none;
}
button.secondary {
background: var(--col-button-sec);
}
+button.secondary:hover {
+ background: var(--col-button-sec-hl);
+}
+
+button.secondary:active {
+ background: white;
+ color: var(--col-button-sec);
+}
+
button:hover, input[type=submit]:hover {
- filter: grayscale(0.9) brightness(2.5);
+ background: var(--col-button-pri-hl);
}
button:active, input[type=submit]:active {
- filter: grayscale(0.9) brightness(3.5);
+ background: white;
+ color: var(--col-button-pri);
}
input {
@@ -103,3 +123,21 @@ div.dialog.visible {
opacity: 1;
visibility: visible;
}
+
+::-webkit-scrollbar {
+ width: 10px;
+ height: 10px;
+}
+
+::-webkit-scrollbar-thumb {
+ background: var(--col-scrollbar);
+ border-radius: 10px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: var(--col-scrollbar-hover);
+}
+
+::-webkit-scrollbar-corner {
+ opacity: 0;
+}