feat: add sorting and filtering in file list
This commit is contained in:
parent
02279b8c6f
commit
79cd7a32ed
@ -22,6 +22,31 @@
|
|||||||
<div class="title"></div>
|
<div class="title"></div>
|
||||||
<div class="episodes"><span class="num"></span> episode(s)</div>
|
<div class="episodes"><span class="num"></span> episode(s)</div>
|
||||||
</a>
|
</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>
|
<div id="files"></div>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
|
@ -338,9 +338,11 @@ button.improve {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
max-width: 30em;
|
max-width: 30em;
|
||||||
|
transform: translateX(0%);
|
||||||
|
transition: transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1);
|
||||||
|
|
||||||
&:not(.show) {
|
&:not(.show) {
|
||||||
display: none;
|
transform: translateX(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
#close-notifs {
|
#close-notifs {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
grid-auto-rows: 15em;
|
grid-auto-rows: 15em;
|
||||||
gap: 0.8em;
|
gap: 0.8em;
|
||||||
place-items: center;
|
place-items: center;
|
||||||
|
padding: 0.8em 0;
|
||||||
|
|
||||||
.file {
|
.file {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -19,6 +20,10 @@
|
|||||||
padding: 0.4em;
|
padding: 0.4em;
|
||||||
border-radius: 1.2em;
|
border-radius: 1.2em;
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: #f8f8f8;
|
background-color: #f8f8f8;
|
||||||
}
|
}
|
||||||
@ -34,4 +39,58 @@
|
|||||||
font-weight: bold;
|
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) {
|
function makeFilm(meta) {
|
||||||
const file = document.getElementById("film-template").cloneNode(true)
|
const file = document.getElementById("film-template").cloneNode(true)
|
||||||
file.querySelector(".title").innerText = meta.title
|
file.querySelector(".title").innerText = meta.title
|
||||||
@ -47,13 +49,59 @@ function addFiles(files) {
|
|||||||
const meta = files[i]
|
const meta = files[i]
|
||||||
const file = makeFile(meta)
|
const file = makeFile(meta)
|
||||||
list.appendChild(file)
|
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", () => {
|
window.addEventListener("load", () => {
|
||||||
fetch("/api/files").then(res => {
|
fetch("/api/files").then(res => {
|
||||||
return res.json()
|
return res.json()
|
||||||
}).then(files => {
|
}).then(files => {
|
||||||
addFiles(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