refactor: move metadata editor to sub-directory
This commit is contained in:
parent
be91526c90
commit
371fb9042d
@ -2,4 +2,6 @@ __pycache__/
|
||||
*.pyc
|
||||
.git
|
||||
.env
|
||||
metadata
|
||||
/to_convert/
|
||||
/converted/
|
||||
/metadata/
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -1 +1,3 @@
|
||||
metadata
|
||||
/to_convert/
|
||||
/converted/
|
||||
/metadata/
|
@ -3,51 +3,28 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Metadata Editor</title>
|
||||
<title>Melies</title>
|
||||
<link rel="stylesheet" href="/static/css/base.css">
|
||||
<link rel="stylesheet" href="/static/css/index.css">
|
||||
<link rel="shortcut icon" href="/static/images/icon3.svg" type="image/svg+xml">
|
||||
<script src="/static/js/index.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Metadata Editor</h1>
|
||||
<img src="/static/images/icon3.svg">
|
||||
<h1>Melies</h1>
|
||||
</header>
|
||||
<main>
|
||||
<a id="film-template" class="template file film">
|
||||
<img src="/static/images/film.svg">
|
||||
<div class="title"></div>
|
||||
<nav id="pages">
|
||||
<a class="page" href="/conversion/">
|
||||
<img src="/static/images/conversion.svg">
|
||||
<div class="name">Conversion</div>
|
||||
</a>
|
||||
<a id="series-template" class="template file series">
|
||||
<img src="/static/images/series.svg">
|
||||
<div class="title"></div>
|
||||
<div class="episodes"><span class="num"></span> episode(s)</div>
|
||||
<a class="page" href="/metadata/">
|
||||
<img src="/static/images/metadata.svg">
|
||||
<div class="name">Metadata</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>
|
||||
</nav>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Edit</title>
|
||||
<title>Melies - Metadata Editor</title>
|
||||
<link rel="stylesheet" href="/static/css/base.css">
|
||||
<link rel="stylesheet" href="/static/css/edit.css">
|
||||
<script src="/static/js/edit.mjs" type="module"></script>
|
||||
@ -14,7 +14,7 @@
|
||||
<img class="clicked" src="/static/images/improve_clicked.svg">
|
||||
</button>
|
||||
<header id="toolbar">
|
||||
<a href="/">Home</a>
|
||||
<a href="/metadata/">Back</a>
|
||||
<button id="check-integrity">Check integrity</button>
|
||||
<button id="improve-all">Improve all names</button>
|
||||
<button id="save">Save</button>
|
54
src/public/metadata/index.html
Normal file
54
src/public/metadata/index.html
Normal file
@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Melies - Metadata Editor</title>
|
||||
<link rel="stylesheet" href="/static/css/base.css">
|
||||
<link rel="stylesheet" href="/static/css/metadata.css">
|
||||
<link rel="shortcut icon" href="/static/images/icon3.svg" type="image/svg+xml">
|
||||
<script src="/static/js/metadata.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>Metadata Editor</h1>
|
||||
</header>
|
||||
<main>
|
||||
<a id="film-template" class="template file film">
|
||||
<img src="/static/images/film.svg">
|
||||
<div class="title"></div>
|
||||
</a>
|
||||
<a id="series-template" class="template file series">
|
||||
<img src="/static/images/series.svg">
|
||||
<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>
|
||||
</html>
|
@ -1,12 +1,23 @@
|
||||
#files {
|
||||
header {
|
||||
align-items: center;
|
||||
img {
|
||||
width: 4em;
|
||||
height: 4em;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
#pages {
|
||||
display: grid;
|
||||
max-width: calc(max(50%, 20em));
|
||||
margin: 0 auto;
|
||||
grid-template-columns: repeat(auto-fit, minmax(15em, 1fr));
|
||||
grid-auto-rows: 15em;
|
||||
gap: 0.8em;
|
||||
place-items: center;
|
||||
padding: 0.8em 0;
|
||||
|
||||
.file {
|
||||
.page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
@ -20,10 +31,6 @@
|
||||
padding: 0.4em;
|
||||
border-radius: 1.2em;
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
@ -33,64 +40,11 @@
|
||||
height: 10em;
|
||||
}
|
||||
|
||||
.title {
|
||||
.name {
|
||||
overflow-wrap: anywhere;
|
||||
text-align: center;
|
||||
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;
|
||||
}
|
||||
}
|
||||
font-size: 150%;
|
||||
}
|
||||
}
|
||||
}
|
96
src/public/static/css/metadata.css
Normal file
96
src/public/static/css/metadata.css
Normal file
@ -0,0 +1,96 @@
|
||||
#files {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(15em, 1fr));
|
||||
grid-auto-rows: 15em;
|
||||
gap: 0.8em;
|
||||
place-items: center;
|
||||
padding: 0.8em 0;
|
||||
|
||||
.file {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
padding: 0.4em;
|
||||
border-radius: 1.2em;
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 10em;
|
||||
height: 10em;
|
||||
}
|
||||
|
||||
.title {
|
||||
overflow-wrap: anywhere;
|
||||
text-align: center;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
107
src/public/static/images/conversion.svg
Normal file
107
src/public/static/images/conversion.svg
Normal file
@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="128"
|
||||
height="128"
|
||||
viewBox="0 0 128 128"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
sodipodi:docname="conversion.svg"
|
||||
inkscape:export-filename="icon3.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="true"
|
||||
inkscape:zoom="8"
|
||||
inkscape:cx="52.5625"
|
||||
inkscape:cy="60.0625"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1">
|
||||
<inkscape:grid
|
||||
id="grid1"
|
||||
units="px"
|
||||
originx="0"
|
||||
originy="0"
|
||||
spacingx="1"
|
||||
spacingy="1"
|
||||
empcolor="#0099e5"
|
||||
empopacity="0.30196078"
|
||||
color="#0099e5"
|
||||
opacity="0.14901961"
|
||||
empspacing="16"
|
||||
enabled="true"
|
||||
visible="true" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs1">
|
||||
<inkscape:path-effect
|
||||
effect="fillet_chamfer"
|
||||
id="path-effect18"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
nodesatellites_param="F,0,0,1,0,2.2320508,0,1 @ F,0,1,1,0,2.2320508,0,1 @ F,0,1,1,0,2.2320508,0,1"
|
||||
radius="0"
|
||||
unit="px"
|
||||
method="auto"
|
||||
mode="F"
|
||||
chamfer_steps="1"
|
||||
flexible="false"
|
||||
use_knot_distance="true"
|
||||
apply_no_radius="true"
|
||||
apply_with_radius="true"
|
||||
only_selected="false"
|
||||
hide_knots="false" />
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g13"
|
||||
transform="matrix(1.21875,0,0,1.21875,-13.728742,-14)">
|
||||
<path
|
||||
id="path14"
|
||||
style="fill:none;stroke:#000000;stroke-width:1.64103;stroke-linecap:round;stroke-linejoin:round"
|
||||
d="m 30.956917,64 c 0,-18.126268 14.694243,-32.820511 32.820511,-32.820511 M 96.597939,64 c 0,18.126268 -14.694243,32.820511 -32.820511,32.820511"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.64103;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 57.213327,24.615384 6.564102,6.564103 -6.564102,6.564102"
|
||||
id="path15" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1.64103;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 70.341532,103.38461 63.777429,96.820512 70.341532,90.25641"
|
||||
id="path16" />
|
||||
</g>
|
||||
<path
|
||||
id="path17"
|
||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 40 39 L 40 89 L 48 89 L 48 85 L 80 85 L 80 89 L 88 89 L 88 39 L 80 39 L 80 44 L 48 44 L 48 39 L 40 39 z M 42 44.5 L 46 44.5 L 46 47.5 L 42 47.5 L 42 44.5 z M 82 44.5 L 86 44.5 L 86 47.5 L 82 47.5 L 82 44.5 z M 48 48 L 80 48 L 80 80 L 48 80 L 48 48 z M 42 50.5 L 46 50.5 L 46 53.5 L 42 53.5 L 42 50.5 z M 82 50.5 L 86 50.5 L 86 53.5 L 82 53.5 L 82 50.5 z M 42 56.5 L 46 56.5 L 46 59.5 L 42 59.5 L 42 56.5 z M 82 56.5 L 86 56.5 L 86 59.5 L 82 59.5 L 82 56.5 z M 42 62.5 L 46 62.5 L 46 65.5 L 42 65.5 L 42 62.5 z M 82 62.5 L 86 62.5 L 86 65.5 L 82 65.5 L 82 62.5 z M 42 68.5 L 46 68.5 L 46 71.5 L 42 71.5 L 42 68.5 z M 82 68.5 L 86 68.5 L 86 71.5 L 82 71.5 L 82 68.5 z M 42 74.5 L 46 74.5 L 46 77.5 L 42 77.5 L 42 74.5 z M 82 74.5 L 86 74.5 L 86 77.5 L 82 77.5 L 82 74.5 z M 42 80.5 L 46 80.5 L 46 83.5 L 42 83.5 L 42 80.5 z M 82 80.5 L 86 80.5 L 86 83.5 L 82 83.5 L 82 80.5 z " />
|
||||
<path
|
||||
id="path18"
|
||||
style="stroke-width:2;stroke-linecap:round;stroke-linejoin:round"
|
||||
inkscape:transform-center-x="-2.25"
|
||||
d="m 71.066987,65.116025 -9.633974,5.562179 A 1.2886751,1.2886751 29.999999 0 1 59.5,69.562178 V 58.437822 a 1.2886751,1.2886751 150 0 1 1.933013,-1.116026 l 9.633974,5.562179 a 1.2886752,1.2886752 90 0 1 0,2.23205 z"
|
||||
inkscape:path-effect="#path-effect18"
|
||||
inkscape:original-d="M 73,64 59.5,71.794229 V 56.205771 Z" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.6 KiB |
129
src/public/static/images/icon3.svg
Normal file
129
src/public/static/images/icon3.svg
Normal file
@ -0,0 +1,129 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="128"
|
||||
height="128"
|
||||
viewBox="0 0 128 128"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
sodipodi:docname="icon3.svg"
|
||||
inkscape:export-filename="icon3.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="4"
|
||||
inkscape:cx="100.625"
|
||||
inkscape:cy="71.125"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g13">
|
||||
<inkscape:grid
|
||||
id="grid1"
|
||||
units="px"
|
||||
originx="0"
|
||||
originy="0"
|
||||
spacingx="1"
|
||||
spacingy="1"
|
||||
empcolor="#0099e5"
|
||||
empopacity="0.30196078"
|
||||
color="#0099e5"
|
||||
opacity="0.14901961"
|
||||
empspacing="16"
|
||||
enabled="true"
|
||||
visible="false" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g13"
|
||||
transform="matrix(1.21875,0,0,1.21875,-13.728742,-14)">
|
||||
<circle
|
||||
style="fill:#d7d7d7;fill-opacity:1;stroke:none;stroke-width:1.99937;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||
id="path8"
|
||||
cx="64"
|
||||
cy="64"
|
||||
r="48" />
|
||||
<g
|
||||
id="g6"
|
||||
transform="matrix(0.94549245,0.64625754,-0.64625754,0.94549245,16.322685,-59.513608)"
|
||||
inkscape:transform-center-x="21.678799"
|
||||
inkscape:transform-center-y="-15.571769">
|
||||
<path
|
||||
style="fill:#cb5739;fill-opacity:1;stroke:#434343;stroke-width:1.99937;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 48,56 v 16 h 32 l 8,-8 -8,-8 z"
|
||||
id="path2" />
|
||||
<g
|
||||
id="g5"
|
||||
transform="translate(2.5)"
|
||||
style="stroke:#434343;stroke-opacity:1">
|
||||
<path
|
||||
style="fill:none;stroke:#434343;stroke-width:1.99937;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 57,60 -4,4 4,4"
|
||||
id="path3" />
|
||||
<path
|
||||
style="fill:none;stroke:#434343;stroke-width:1.99937;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 61,68 5,-8"
|
||||
id="path4" />
|
||||
<path
|
||||
style="fill:none;stroke:#434343;stroke-width:1.99937;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||
d="m 70,60 4,4 -4,4"
|
||||
id="path5" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g14"
|
||||
inkscape:transform-center-x="-7.5111916"
|
||||
inkscape:transform-center-y="2.6415215"
|
||||
transform="matrix(1.1647434,0,0,1.1647434,-10.506912,-10.543579)">
|
||||
<path
|
||||
style="fill:#434343;fill-opacity:1;stroke:#434343;stroke-width:1.40891602;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 75.224968,50.967861 c 0,-0.542977 2.520211,-2.301228 4.451793,-2.109964 1.931582,0.191264 2.893913,2.267985 4.451792,3.230807 1.55788,0.962823 4.451793,1.235924 4.451793,1.847019 0,0.611095 -2.828267,0.995112 -3.929854,0.735062 -1.101587,-0.26005 -2.00587,-0.735062 -2.00587,-0.735062 0,0 -0.992464,4.709936 -2.967861,4.451792 -1.975397,-0.258143 -1.877599,-5.084776 -1.483931,-7.419654 -0.959231,0.180342 -2.967862,0.542978 -2.967862,0 z"
|
||||
id="path9"
|
||||
sodipodi:nodetypes="zzzzzczcz" />
|
||||
<path
|
||||
style="fill:#434343;fill-opacity:1;stroke:#434343;stroke-width:1.40891602;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="M 48.202298,89.998339 C 46.622528,88.418569 54.521379,83.679258 64,83.679258 c 9.478621,0 17.377472,4.739311 15.797702,6.319081 -1.579771,1.57977 -4.048161,-3.15954 -15.797702,-3.15954 -11.749541,0 -14.217931,4.73931 -15.797702,3.15954 z"
|
||||
id="path10"
|
||||
sodipodi:nodetypes="zzzzz" />
|
||||
<path
|
||||
style="fill:#434343;fill-opacity:1;stroke:#434343;stroke-width:1.40892;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 64,90.410017 c 1.57977,0 4.73931,0 4.73931,1.57977 0,1.579771 -3.15954,1.579771 -4.73931,1.579771 -1.57977,0 -4.73931,0 -4.73931,-1.579771 0,-1.57977 3.15954,-1.57977 4.73931,-1.57977 z"
|
||||
id="path11"
|
||||
sodipodi:nodetypes="zzzzz" />
|
||||
<path
|
||||
style="fill:#434343;fill-opacity:1;stroke:#434343;stroke-width:1.40891602;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 70.683501,47.557279 c 0.05473,-1.03795 1.098384,-1.720698 2.191237,-3.200114 1.092852,-1.479415 3.628351,-4.908029 6.407696,-5.223061 2.779343,-0.315033 13.286146,0.908682 13.91289,1.810272 0.847011,1.218452 -12.113125,-2.037935 -15.945302,1.886694 -3.832177,3.924627 -6.621251,5.76416 -6.566521,4.726209 z"
|
||||
id="path12"
|
||||
sodipodi:nodetypes="zzzszz" />
|
||||
<path
|
||||
style="fill:#434343;fill-opacity:1;stroke:#434343;stroke-width:1.40891602;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 45,80 c 1,0 7,-9 9,-9 2,0 7,3 10,3 3,0 8,-3 10,-3 2,0 8,9 9,9 1,0 -6,-11 -7,-12 -1,-1 -11,4 -12,4 -1,0 -11,-5 -12,-4 -1,1 -8,12 -7,12 z"
|
||||
id="path13"
|
||||
sodipodi:nodetypes="zzzzzzzzz" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.9 KiB |
92
src/public/static/images/metadata.svg
Normal file
92
src/public/static/images/metadata.svg
Normal file
@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="128"
|
||||
height="128"
|
||||
viewBox="0 0 128 128"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
sodipodi:docname="metadata.svg"
|
||||
inkscape:export-filename="icon3.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="true"
|
||||
inkscape:zoom="5.6568543"
|
||||
inkscape:cx="56.303377"
|
||||
inkscape:cy="65.672542"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g13">
|
||||
<inkscape:grid
|
||||
id="grid1"
|
||||
units="px"
|
||||
originx="0"
|
||||
originy="0"
|
||||
spacingx="1"
|
||||
spacingy="1"
|
||||
empcolor="#0099e5"
|
||||
empopacity="0.30196078"
|
||||
color="#0099e5"
|
||||
opacity="0.14901961"
|
||||
empspacing="16"
|
||||
enabled="true"
|
||||
visible="true" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs1" />
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<g
|
||||
id="g13"
|
||||
transform="matrix(1.21875,0,0,1.21875,-13.728742,-14)">
|
||||
<g
|
||||
id="g6"
|
||||
transform="matrix(1.7902099,0,0,1.7902099,-54.376425,-50.573434)"
|
||||
inkscape:transform-center-x="-4.3636355"
|
||||
style="stroke:#000000;stroke-opacity:1;fill:none;fill-opacity:1;stroke-width:0.91666661;stroke-dasharray:none">
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.91666661;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 48,56 v 16 h 32 l 8,-8 -8,-8 z"
|
||||
id="path2" />
|
||||
<g
|
||||
id="g5"
|
||||
transform="translate(2.5)"
|
||||
style="stroke:#000000;stroke-opacity:1;fill:none;fill-opacity:1;stroke-width:0.91666661;stroke-dasharray:none">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.91666661;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1;stroke-dasharray:none"
|
||||
d="m 57,60 -4,4 4,4"
|
||||
id="path3" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.91666661;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1;stroke-dasharray:none"
|
||||
d="m 61,68 5,-8"
|
||||
id="path4" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:0.91666661;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1;fill-opacity:1;stroke-dasharray:none"
|
||||
d="m 70,60 4,4 -4,4"
|
||||
id="path5" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.1 KiB |
@ -1,107 +0,0 @@
|
||||
let fileNodes = []
|
||||
|
||||
function makeFilm(meta) {
|
||||
const file = document.getElementById("film-template").cloneNode(true)
|
||||
file.querySelector(".title").innerText = meta.title
|
||||
return file
|
||||
}
|
||||
|
||||
function makeSeries(meta) {
|
||||
const file = document.getElementById("series-template").cloneNode(true)
|
||||
file.querySelector(".title").innerText = meta.title
|
||||
file.querySelector(".episodes .num").innerText = meta.episodes
|
||||
return file
|
||||
}
|
||||
|
||||
function makeFile(meta) {
|
||||
let file
|
||||
switch (meta.type) {
|
||||
case "film":
|
||||
file = makeFilm(meta)
|
||||
break
|
||||
case "series":
|
||||
file = makeSeries(meta)
|
||||
break
|
||||
default:
|
||||
throw new Error(`Invalid file type '${meta.type}'`)
|
||||
}
|
||||
|
||||
file.title = meta.filename
|
||||
file.id = null
|
||||
file.classList.remove("template")
|
||||
const url = new URL("/edit/", window.location.origin)
|
||||
url.searchParams.set("f", meta.filename)
|
||||
file.href = url.href
|
||||
return file
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object[]} files
|
||||
*/
|
||||
function addFiles(files) {
|
||||
const list = document.getElementById("files")
|
||||
list.innerHTML = ""
|
||||
const filenames = files.map(meta => meta.filename)
|
||||
// Copy array because sort changes it in place
|
||||
Array.from(filenames).sort().forEach(filename => {
|
||||
const i = filenames.indexOf(filename)
|
||||
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())
|
||||
})
|
107
src/public/static/js/metadata.js
Normal file
107
src/public/static/js/metadata.js
Normal file
@ -0,0 +1,107 @@
|
||||
let fileNodes = []
|
||||
|
||||
function makeFilm(meta) {
|
||||
const file = document.getElementById("film-template").cloneNode(true)
|
||||
file.querySelector(".title").innerText = meta.title
|
||||
return file
|
||||
}
|
||||
|
||||
function makeSeries(meta) {
|
||||
const file = document.getElementById("series-template").cloneNode(true)
|
||||
file.querySelector(".title").innerText = meta.title
|
||||
file.querySelector(".episodes .num").innerText = meta.episodes
|
||||
return file
|
||||
}
|
||||
|
||||
function makeFile(meta) {
|
||||
let file
|
||||
switch (meta.type) {
|
||||
case "film":
|
||||
file = makeFilm(meta)
|
||||
break
|
||||
case "series":
|
||||
file = makeSeries(meta)
|
||||
break
|
||||
default:
|
||||
throw new Error(`Invalid file type '${meta.type}'`)
|
||||
}
|
||||
|
||||
file.title = meta.filename
|
||||
file.id = null
|
||||
file.classList.remove("template")
|
||||
const url = new URL("/metadata/edit/", window.location.origin)
|
||||
url.searchParams.set("f", meta.filename)
|
||||
file.href = url.href
|
||||
return file
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object[]} files
|
||||
*/
|
||||
function addFiles(files) {
|
||||
const list = document.getElementById("files")
|
||||
list.innerHTML = ""
|
||||
const filenames = files.map(meta => meta.filename)
|
||||
// Copy array because sort changes it in place
|
||||
Array.from(filenames).sort().forEach(filename => {
|
||||
const i = filenames.indexOf(filename)
|
||||
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())
|
||||
})
|
Loading…
x
Reference in New Issue
Block a user