diff options
| -rw-r--r-- | Pages/Shared/_Layout.cshtml.css | 2 | ||||
| -rw-r--r-- | Pages/TagDefinitions.cshtml | 12 | ||||
| -rw-r--r-- | Pages/TagDefinitions.cshtml.css | 4 | ||||
| -rw-r--r-- | Pages/ViewMedia.cshtml | 59 | ||||
| -rw-r--r-- | Pages/ViewMedia.cshtml.cs | 3 | ||||
| -rw-r--r-- | Pages/ViewMedia.cshtml.css | 38 | ||||
| -rw-r--r-- | wwwroot/styles/global.css | 56 |
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; +} |
