feat: add support for series
This commit is contained in:
parent
bc5371de71
commit
ed3c6d7cc7
@ -23,6 +23,12 @@
|
|||||||
</header>
|
</header>
|
||||||
<main id="main">
|
<main id="main">
|
||||||
<h1>Editing <code id="filename"></code><span id="unsaved"> - Unsaved</span></h1>
|
<h1>Editing <code id="filename"></code><span id="unsaved"> - Unsaved</span></h1>
|
||||||
|
<div id="series-toolbar">
|
||||||
|
<button id="prev-episode"></button>
|
||||||
|
<div id="cur-episode"></div>
|
||||||
|
<button id="next-episode"></button>
|
||||||
|
</div>
|
||||||
|
<div class="sep"></div>
|
||||||
<div class="fields">
|
<div class="fields">
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label for="title">Title</label>
|
<label for="title">Title</label>
|
||||||
|
@ -337,6 +337,7 @@ button.improve {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
max-width: 30em;
|
||||||
|
|
||||||
&:not(.show) {
|
&:not(.show) {
|
||||||
display: none;
|
display: none;
|
||||||
@ -369,4 +370,44 @@ button.improve {
|
|||||||
padding: 0.4em;
|
padding: 0.4em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sep {
|
||||||
|
border-bottom: solid black 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#series-toolbar {
|
||||||
|
display: flex;
|
||||||
|
gap: 0.4em;
|
||||||
|
padding: 0.4em;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&:not(.show) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: var(--img);
|
||||||
|
width: 2.4em;
|
||||||
|
height: 2.4em;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
background-size: 80%;
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: 0.4em;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&#prev-episode {
|
||||||
|
--img: url("/static/images/prev.svg");
|
||||||
|
}
|
||||||
|
|
||||||
|
&#next-episode {
|
||||||
|
--img: url("/static/images/next.svg");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
64
editor/public/static/images/next.svg
Normal file
64
editor/public/static/images/next.svg
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="64mm"
|
||||||
|
height="64mm"
|
||||||
|
viewBox="0 0 64 64"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
|
||||||
|
sodipodi:docname="next_icon.svg"
|
||||||
|
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="2.0560856"
|
||||||
|
inkscape:cx="8.7544994"
|
||||||
|
inkscape:cy="178.49452"
|
||||||
|
inkscape:window-width="1858"
|
||||||
|
inkscape:window-height="1016"
|
||||||
|
inkscape:window-x="1982"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<inkscape:grid
|
||||||
|
id="grid1"
|
||||||
|
units="px"
|
||||||
|
originx="0"
|
||||||
|
originy="0"
|
||||||
|
spacingx="0.26458333"
|
||||||
|
spacingy="0.26458333"
|
||||||
|
empcolor="#0099e5"
|
||||||
|
empopacity="0.30196078"
|
||||||
|
color="#0099e5"
|
||||||
|
opacity="0.14901961"
|
||||||
|
empspacing="8"
|
||||||
|
dotted="false"
|
||||||
|
gridanglex="30"
|
||||||
|
gridanglez="30"
|
||||||
|
visible="true" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
style="color:#000000;fill:#000000;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
|
||||||
|
d="m 19.698341,10.884614 a 4.2333331,4.2333331 0 0 0 -2.763672,1.691406 4.2333331,4.2333331 0 0 0 0.933594,5.914062 L 36.444435,31.999848 17.868263,45.509614 a 4.2333331,4.2333331 0 0 0 -0.933594,5.914062 4.2333331,4.2333331 0 0 0 5.914063,0.933594 L 46.131935,35.423676 a 4.2337564,4.2337564 0 0 0 0,-6.847656 L 22.848732,11.642426 a 4.2333331,4.2333331 0 0 0 -3.150391,-0.757812 z"
|
||||||
|
id="path1" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
64
editor/public/static/images/prev.svg
Normal file
64
editor/public/static/images/prev.svg
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width="64mm"
|
||||||
|
height="64mm"
|
||||||
|
viewBox="0 0 64 64"
|
||||||
|
version="1.1"
|
||||||
|
id="svg1"
|
||||||
|
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
|
||||||
|
sodipodi:docname="prev_icon.svg"
|
||||||
|
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="2.0560856"
|
||||||
|
inkscape:cx="8.7544994"
|
||||||
|
inkscape:cy="178.49452"
|
||||||
|
inkscape:window-width="1858"
|
||||||
|
inkscape:window-height="1016"
|
||||||
|
inkscape:window-x="1982"
|
||||||
|
inkscape:window-y="27"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="layer1">
|
||||||
|
<inkscape:grid
|
||||||
|
id="grid1"
|
||||||
|
units="px"
|
||||||
|
originx="0"
|
||||||
|
originy="0"
|
||||||
|
spacingx="0.26458333"
|
||||||
|
spacingy="0.26458333"
|
||||||
|
empcolor="#0099e5"
|
||||||
|
empopacity="0.30196078"
|
||||||
|
color="#0099e5"
|
||||||
|
opacity="0.14901961"
|
||||||
|
empspacing="8"
|
||||||
|
dotted="false"
|
||||||
|
gridanglex="30"
|
||||||
|
gridanglez="30"
|
||||||
|
visible="true" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<defs
|
||||||
|
id="defs1" />
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<path
|
||||||
|
style="color:#000000;fill:#000000;stroke-linecap:round;stroke-linejoin:round;-inkscape-stroke:none"
|
||||||
|
d="m 44.301659,10.884614 a 4.2333331,4.2333331 0 0 1 2.763672,1.691406 4.2333331,4.2333331 0 0 1 -0.933594,5.914062 L 27.555565,31.999848 46.131737,45.509614 a 4.2333331,4.2333331 0 0 1 0.933594,5.914062 4.2333331,4.2333331 0 0 1 -5.914063,0.933594 L 17.868065,35.423676 a 4.2337564,4.2337564 0 0 1 0,-6.847656 L 41.151268,11.642426 a 4.2333331,4.2333331 0 0 1 3.150391,-0.757812 z"
|
||||||
|
id="path1" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
@ -1,6 +1,7 @@
|
|||||||
import TracksTable from "./tracks_table.mjs"
|
import TracksTable from "./tracks_table.mjs"
|
||||||
import IntegrityManager from "./integrity_manager.mjs"
|
import IntegrityManager from "./integrity_manager.mjs"
|
||||||
import { updateObjectFromJoinedKey } from "./utils.mjs"
|
import { updateObjectFromJoinedKey } from "./utils.mjs"
|
||||||
|
import { loadMetadata, SeriesMetadata } from "./metadata.mjs"
|
||||||
|
|
||||||
export default class Editor {
|
export default class Editor {
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -18,10 +19,11 @@ export default class Editor {
|
|||||||
subtitle: new TracksTable(this, "subtitle", "subtitle-tracks", "subtitle_tracks")
|
subtitle: new TracksTable(this, "subtitle", "subtitle-tracks", "subtitle_tracks")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.metadata = null
|
||||||
this.data = {}
|
this.data = {}
|
||||||
this.dirty = false
|
this.dirty = false
|
||||||
|
|
||||||
this.integrity_mgr = new IntegrityManager(this)
|
this.integrityMgr = new IntegrityManager(this)
|
||||||
|
|
||||||
document.getElementById("check-integrity").addEventListener("click", () => this.checkIntegrity())
|
document.getElementById("check-integrity").addEventListener("click", () => this.checkIntegrity())
|
||||||
document.getElementById("improve-all").addEventListener("click", () => this.improveAllNames())
|
document.getElementById("improve-all").addEventListener("click", () => this.improveAllNames())
|
||||||
@ -29,6 +31,14 @@ export default class Editor {
|
|||||||
document.getElementById("reload").addEventListener("click", () => window.location.reload())
|
document.getElementById("reload").addEventListener("click", () => window.location.reload())
|
||||||
document.getElementById("toggle-notifs").addEventListener("click", () => this.toggleNotifications())
|
document.getElementById("toggle-notifs").addEventListener("click", () => this.toggleNotifications())
|
||||||
document.getElementById("close-notifs").addEventListener("click", () => this.closeNotifications())
|
document.getElementById("close-notifs").addEventListener("click", () => this.closeNotifications())
|
||||||
|
document.getElementById("prev-episode").addEventListener("click", () => this.prevEpisode())
|
||||||
|
document.getElementById("next-episode").addEventListener("click", () => this.nextEpisode())
|
||||||
|
|
||||||
|
this.titleInput = document.getElementById("title")
|
||||||
|
this.titleInput.addEventListener("change", () => {
|
||||||
|
this.data.title = this.titleInput.value
|
||||||
|
this.setDirty()
|
||||||
|
})
|
||||||
|
|
||||||
this.setup()
|
this.setup()
|
||||||
}
|
}
|
||||||
@ -46,14 +56,27 @@ export default class Editor {
|
|||||||
return null
|
return null
|
||||||
}).then(res => {
|
}).then(res => {
|
||||||
if (res !== null) {
|
if (res !== null) {
|
||||||
this.data = res
|
this.metadata = loadMetadata(res)
|
||||||
this.displayData()
|
this.displayData()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
displayData() {
|
displayData() {
|
||||||
document.getElementById("title").value = this.data.title
|
const seriesToolbar = document.getElementById("series-toolbar")
|
||||||
|
if (this.metadata instanceof SeriesMetadata) {
|
||||||
|
seriesToolbar.classList.add("show")
|
||||||
|
const cur = this.metadata.episodeIdx + 1
|
||||||
|
const tot = this.metadata.episodes.length
|
||||||
|
const epMeta = this.metadata.getCurrentEpisode()
|
||||||
|
const season = epMeta.season
|
||||||
|
const episode = epMeta.episode
|
||||||
|
seriesToolbar.querySelector("#cur-episode").innerText = `S${season}E${episode} (${cur} / ${tot})`
|
||||||
|
} else {
|
||||||
|
seriesToolbar.classList.remove("show")
|
||||||
|
}
|
||||||
|
this.data = this.metadata.getData()
|
||||||
|
this.titleInput.value = this.data.title
|
||||||
this.tables.audio.loadTracks(this.data.audio_tracks)
|
this.tables.audio.loadTracks(this.data.audio_tracks)
|
||||||
this.tables.subtitle.loadTracks(this.data.subtitle_tracks)
|
this.tables.subtitle.loadTracks(this.data.subtitle_tracks)
|
||||||
}
|
}
|
||||||
@ -61,7 +84,7 @@ export default class Editor {
|
|||||||
save() {
|
save() {
|
||||||
fetch(`/api/file/${this.filename}`, {
|
fetch(`/api/file/${this.filename}`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: JSON.stringify(this.data),
|
body: JSON.stringify(this.metadata.data),
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
}
|
}
|
||||||
@ -100,13 +123,13 @@ export default class Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkIntegrity() {
|
checkIntegrity() {
|
||||||
if (this.integrity_mgr.checkIntegrity()) {
|
if (this.integrityMgr.checkIntegrity()) {
|
||||||
this.notify("No integrity error detected !", "success")
|
this.notify("No integrity error detected !", "success")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
improveAllNames() {
|
improveAllNames() {
|
||||||
this.integrity_mgr.improveAllNames()
|
this.integrityMgr.improveAllNames()
|
||||||
this.notify("Improved all names !", "success")
|
this.notify("Improved all names !", "success")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,4 +151,20 @@ export default class Editor {
|
|||||||
const hist = document.getElementById("notifs-hist")
|
const hist = document.getElementById("notifs-hist")
|
||||||
hist.classList.remove("show")
|
hist.classList.remove("show")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prevEpisode() {
|
||||||
|
if (this.metadata instanceof SeriesMetadata) {
|
||||||
|
if (this.metadata.prev()) {
|
||||||
|
this.displayData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nextEpisode() {
|
||||||
|
if (this.metadata instanceof SeriesMetadata) {
|
||||||
|
if (this.metadata.next()) {
|
||||||
|
this.displayData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ function addOptions(files) {
|
|||||||
defaultOpt.innerText = "----- Select a file -----"
|
defaultOpt.innerText = "----- Select a file -----"
|
||||||
defaultOpt.value = ""
|
defaultOpt.value = ""
|
||||||
select.appendChild(defaultOpt)
|
select.appendChild(defaultOpt)
|
||||||
files.forEach(file => {
|
files.sort().forEach(file => {
|
||||||
const option = document.createElement("option")
|
const option = document.createElement("option")
|
||||||
option.innerText = file
|
option.innerText = file
|
||||||
option.value = file
|
option.value = file
|
||||||
|
5
editor/public/static/js/media_file.mjs
Normal file
5
editor/public/static/js/media_file.mjs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export default class MediaFile {
|
||||||
|
constructor(data) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
85
editor/public/static/js/metadata.mjs
Normal file
85
editor/public/static/js/metadata.mjs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
export default class Metadata {
|
||||||
|
constructor(data) {
|
||||||
|
this.data = data
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
return this.data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class MediaMetadata extends Metadata {
|
||||||
|
constructor(data) {
|
||||||
|
super(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class EpisodeMetadata extends MediaMetadata {
|
||||||
|
REGEXP = /s(?<season>\d+)e(?<episode>\d+)/i
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} data
|
||||||
|
* @param {string} episodeKey
|
||||||
|
*/
|
||||||
|
constructor(data, episodeKey) {
|
||||||
|
super(data)
|
||||||
|
this.key = episodeKey
|
||||||
|
|
||||||
|
let m = this.key.match(this.REGEXP) ?? this.data.filename.match(this.REGEXP)
|
||||||
|
this.season = "xx"
|
||||||
|
this.episode = "xx"
|
||||||
|
if (m) {
|
||||||
|
this.season = m.groups.season
|
||||||
|
this.episode = m.groups.episode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SeriesMetadata extends Metadata {
|
||||||
|
constructor(data) {
|
||||||
|
super(data)
|
||||||
|
const episodeKeys = Object.keys(data).sort()
|
||||||
|
this.episodes = episodeKeys.map(key => {
|
||||||
|
return new EpisodeMetadata(data[key], key)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.episodeIdx = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentEpisode() {
|
||||||
|
return this.episodes[this.episodeIdx]
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
return this.getCurrentEpisode().getData()
|
||||||
|
}
|
||||||
|
|
||||||
|
prev() {
|
||||||
|
if (this.episodeIdx === 0) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.episodeIdx -= 1
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
next() {
|
||||||
|
if (this.episodeIdx === this.episodes.length - 1) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
this.episodeIdx += 1
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} data
|
||||||
|
* @returns {Metadata}
|
||||||
|
*/
|
||||||
|
export function loadMetadata(data) {
|
||||||
|
if ("filename" in data) {
|
||||||
|
return new MediaMetadata(data)
|
||||||
|
}
|
||||||
|
return new SeriesMetadata(data)
|
||||||
|
}
|
@ -113,6 +113,7 @@ export class Track {
|
|||||||
"warning"
|
"warning"
|
||||||
)
|
)
|
||||||
value = lang
|
value = lang
|
||||||
|
this.editValue(field.key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,19 +141,21 @@ export class Track {
|
|||||||
this.table.editTrack(this.idx, key, value)
|
this.table.editTrack(this.idx, key, value)
|
||||||
|
|
||||||
const input = this.row.querySelector(`[data-key='${key}']`)
|
const input = this.row.querySelector(`[data-key='${key}']`)
|
||||||
const fieldType = this.table.getFieldProps(key).type
|
if (input) {
|
||||||
switch (fieldType) {
|
const fieldType = this.table.getFieldProps(key).type
|
||||||
case "bool":
|
switch (fieldType) {
|
||||||
input.checked = value
|
case "bool":
|
||||||
break
|
input.checked = value
|
||||||
default:
|
break
|
||||||
input.value = value
|
default:
|
||||||
break
|
input.value = value
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
improveName() {
|
improveName() {
|
||||||
this.table.editor.integrity_mgr.improveName(this)
|
this.table.editor.integrityMgr.improveName(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,9 +187,10 @@ export default class TracksTable {
|
|||||||
this.table = document.getElementById(tableId)
|
this.table = document.getElementById(tableId)
|
||||||
this.headers = this.table.querySelector("thead tr")
|
this.headers = this.table.querySelector("thead tr")
|
||||||
this.body = this.table.querySelector("tbody")
|
this.body = this.table.querySelector("tbody")
|
||||||
this.fields = []
|
|
||||||
this.tracks = []
|
|
||||||
this.dataKey = dataKey
|
this.dataKey = dataKey
|
||||||
|
|
||||||
|
this.tracks = []
|
||||||
|
this.fields = []
|
||||||
this.onehots = {}
|
this.onehots = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -195,8 +199,8 @@ export default class TracksTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadTracks(tracks) {
|
loadTracks(tracks) {
|
||||||
this.tracks = tracks.map((t, i) => new Track(this, i, t))
|
|
||||||
this.clear()
|
this.clear()
|
||||||
|
this.tracks = tracks.map((t, i) => new Track(this, i, t))
|
||||||
if (tracks.length === 0) {
|
if (tracks.length === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -208,9 +212,11 @@ export default class TracksTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
|
this.tracks = []
|
||||||
|
this.fields = []
|
||||||
|
this.onehots = {}
|
||||||
this.headers.innerHTML = ""
|
this.headers.innerHTML = ""
|
||||||
this.body.innerHTML = ""
|
this.body.innerHTML = ""
|
||||||
this.fields = []
|
|
||||||
}
|
}
|
||||||
|
|
||||||
detectFields() {
|
detectFields() {
|
||||||
|
@ -41,6 +41,11 @@ export const LANGUAGES = {
|
|||||||
code: "de",
|
code: "de",
|
||||||
aliases: ["de", "ger", "german", "allemand", "deutsch", "germany", "allemagne"]
|
aliases: ["de", "ger", "german", "allemand", "deutsch", "germany", "allemagne"]
|
||||||
},
|
},
|
||||||
|
"ita": {
|
||||||
|
display: "Italiano",
|
||||||
|
code: "it",
|
||||||
|
aliases: ["it", "ita", "italian", "italien", "italiano", "italy", "italie"]
|
||||||
|
},
|
||||||
"kor": {
|
"kor": {
|
||||||
display: "Korean",
|
display: "Korean",
|
||||||
code: "kr",
|
code: "kr",
|
||||||
@ -64,7 +69,7 @@ export const LANGUAGES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getLanguageAliases(langTag) {
|
export function getLanguageAliases(langTag) {
|
||||||
return (langTag === "und" ? [] : [langTag]).concat(LANGUAGES[langTag].aliases)
|
return [langTag].concat(LANGUAGES[langTag].aliases)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,7 +22,6 @@ class MyHandler(SimpleHTTPRequestHandler):
|
|||||||
self.data: Optional[dict|list] = None
|
self.data: Optional[dict|list] = None
|
||||||
|
|
||||||
def read_body_data(self):
|
def read_body_data(self):
|
||||||
self.log_message("Reading body data")
|
|
||||||
try:
|
try:
|
||||||
size: int = int(self.headers["Content-Length"])
|
size: int = int(self.headers["Content-Length"])
|
||||||
if size > MAX_SIZE:
|
if size > MAX_SIZE:
|
||||||
@ -54,7 +53,7 @@ class MyHandler(SimpleHTTPRequestHandler):
|
|||||||
self.send_error(HTTPStatus.NOT_FOUND)
|
self.send_error(HTTPStatus.NOT_FOUND)
|
||||||
|
|
||||||
def handle_api_get(self, path: str):
|
def handle_api_get(self, path: str):
|
||||||
print(f"API request at {path}")
|
self.log_message(f"API request at {path}")
|
||||||
if path == "files":
|
if path == "files":
|
||||||
files: list[str] = self.get_files()
|
files: list[str] = self.get_files()
|
||||||
self.send_json(files)
|
self.send_json(files)
|
||||||
@ -63,9 +62,7 @@ class MyHandler(SimpleHTTPRequestHandler):
|
|||||||
data = self.read_file(filename)
|
data = self.read_file(filename)
|
||||||
if data is None:
|
if data is None:
|
||||||
self.send_error(HTTPStatus.NOT_FOUND)
|
self.send_error(HTTPStatus.NOT_FOUND)
|
||||||
self.log_message("File not found")
|
|
||||||
else:
|
else:
|
||||||
self.log_message("Got file")
|
|
||||||
self.send_json(data)
|
self.send_json(data)
|
||||||
else:
|
else:
|
||||||
self.send_response(HTTPStatus.NOT_FOUND, f"Unknown path {path}")
|
self.send_response(HTTPStatus.NOT_FOUND, f"Unknown path {path}")
|
||||||
@ -104,8 +101,8 @@ class MyHandler(SimpleHTTPRequestHandler):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(os.path.join(self.DATA_DIR, filename), "w") as f:
|
with open(os.path.join(self.DATA_DIR, filename), "w", encoding="utf-8") as f:
|
||||||
json.dump(data, f, indent=2)
|
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||||
except:
|
except:
|
||||||
self.send_error(HTTPStatus.INTERNAL_SERVER_ERROR)
|
self.send_error(HTTPStatus.INTERNAL_SERVER_ERROR)
|
||||||
return False
|
return False
|
||||||
|
Loading…
x
Reference in New Issue
Block a user