feat: Web metadata editor #2
@ -22,6 +22,31 @@
|
||||
<div class="title"></div>
|
||||
<div class="episodes"><span class="num"></span> episode(s)</div>
|
||||
</a>
|
||||
<div class="toolbar">
|
||||
<div class="tool">
|
||||
<label for="sort-by">Sort by</label>
|
||||
<select id="sort-by">
|
||||
<option value="title">Title</option>
|
||||
<option value="ts">Last modified</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="tool">
|
||||
<label for="sort-desc">Order</label>
|
||||
<label class="toggle">
|
||||
<input type="checkbox" id="sort-desc">
|
||||
<div class="off">ASC</div>
|
||||
<div class="on">DESC</div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="tool">
|
||||
<label for="filter">Filter</label>
|
||||
<select id="filter">
|
||||
<option value="all">All</option>
|
||||
<option value="film">Films</option>
|
||||
<option value="series">Series</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="files"></div>
|
||||
</main>
|
||||
</body>
|
||||
|
@ -338,9 +338,11 @@ button.improve {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 30em;
|
||||
transform: translateX(0%);
|
||||
transition: transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
|
||||
|
||||
&:not(.show) {
|
||||
display: none;
|
||||
transform: translateX(100%);
|
||||
}
|
||||
|
||||
#close-notifs {
|
||||
|
@ -4,6 +4,7 @@
|
||||
grid-auto-rows: 15em;
|
||||
gap: 0.8em;
|
||||
place-items: center;
|
||||
padding: 0.8em 0;
|
||||
|
||||
.file {
|
||||
display: flex;
|
||||
@ -19,6 +20,10 @@
|
||||
padding: 0.4em;
|
||||
border-radius: 1.2em;
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
@ -34,4 +39,58 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
display: flex;
|
||||
gap: 1.2em;
|
||||
border-bottom: solid black 1px;
|
||||
padding: 0.4em 0;
|
||||
|
||||
.tool {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.2em;
|
||||
|
||||
label[for] {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
input, select {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
height: 2em;
|
||||
border-radius: 1em;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
|
||||
input {
|
||||
display: none;
|
||||
|
||||
&:not(:checked) ~ .off, &:checked ~ .on {
|
||||
background-color: #6ee74a;
|
||||
}
|
||||
}
|
||||
|
||||
div {
|
||||
padding: 0 0.4em;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
|
||||
&.off {
|
||||
border-radius: 1em 0 0 1em;
|
||||
}
|
||||
|
||||
&.on {
|
||||
border-radius: 0 1em 1em 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
let fileNodes = []
|
||||
|
||||
function makeFilm(meta) {
|
||||
const file = document.getElementById("film-template").cloneNode(true)
|
||||
file.querySelector(".title").innerText = meta.title
|
||||
@ -47,13 +49,59 @@ function addFiles(files) {
|
||||
const meta = files[i]
|
||||
const file = makeFile(meta)
|
||||
list.appendChild(file)
|
||||
fileNodes.push([meta, file])
|
||||
})
|
||||
}
|
||||
|
||||
function sortFiles() {
|
||||
const sortBy = document.getElementById("sort-by").value
|
||||
const sortDesc = document.getElementById("sort-desc").checked
|
||||
const filter = document.getElementById("filter").value
|
||||
|
||||
fileNodes.forEach(([meta, node]) => {
|
||||
if (node.classList.contains(filter) || filter === "all") {
|
||||
node.classList.remove("hidden")
|
||||
} else {
|
||||
node.classList.add("hidden")
|
||||
}
|
||||
})
|
||||
|
||||
let changed = false
|
||||
do {
|
||||
changed = false
|
||||
for (let i = 0; i < fileNodes.length - 1; i++) {
|
||||
/** @type {[object, HTMLElement]} */
|
||||
const pair1 = fileNodes[i]
|
||||
/** @type {[object, HTMLElement]} */
|
||||
const pair2 = fileNodes[i + 1]
|
||||
const [meta1, node1] = pair1
|
||||
const [meta2, node2] = pair2
|
||||
|
||||
let swap = false
|
||||
if (sortDesc) {
|
||||
swap = !(meta1[sortBy] >= meta2[sortBy])
|
||||
} else {
|
||||
swap = !(meta2[sortBy] >= meta1[sortBy])
|
||||
}
|
||||
if (swap) {
|
||||
fileNodes[i] = pair2
|
||||
fileNodes[i + 1] = pair1
|
||||
node2.parentElement.insertBefore(node2, node1)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
} while (changed)
|
||||
}
|
||||
|
||||
window.addEventListener("load", () => {
|
||||
fetch("/api/files").then(res => {
|
||||
return res.json()
|
||||
}).then(files => {
|
||||
addFiles(files)
|
||||
sortFiles()
|
||||
})
|
||||
|
||||
document.getElementById("sort-by").addEventListener("change", () => sortFiles())
|
||||
document.getElementById("sort-desc").addEventListener("click", () => sortFiles())
|
||||
document.getElementById("filter").addEventListener("change", () => sortFiles())
|
||||
})
|
@ -1,5 +0,0 @@
|
||||
export default class MediaFile {
|
||||
constructor(data) {
|
||||
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user