157 lines
4.0 KiB
JavaScript

/** @type TracksTable */
let audioTable
/** @type TracksTable */
let subtitleTable
function flattenObj(obj) {
const res = {}
Object.entries(obj).forEach(([key, value]) => {
if (typeof value === "object") {
value = flattenObj(value)
Object.entries(value).forEach(([key2, value2]) => {
res[key + "/" + key2] = value2
})
} else {
res[key] = value
}
})
return res
}
class TracksTable {
OPTIONS = {
"language": ["fre", "eng"]
}
constructor(table) {
this.table = table
this.headers = this.table.querySelector("thead tr")
this.body = this.table.querySelector("tbody")
this.fields = []
this.tracks = []
}
showTracks(tracks) {
this.tracks = tracks.map(flattenObj)
this.clear()
if (tracks.length === 0) {
return
}
this.detectFields()
this.addHeaders()
this.tracks.forEach((track, i) => {
const tr = document.createElement("tr")
tr.dataset.i = i
this.fields.forEach(field => {
const td = tr.insertCell(-1)
const input = this.makeInput(field, track[field.key])
td.appendChild(input)
})
this.body.appendChild(tr)
})
}
clear() {
this.headers.innerHTML = ""
this.body.innerHTML = ""
this.fields = []
}
detectFields() {
Object.entries(this.tracks[0]).forEach(([key, value]) => {
let type = {
boolean: "bool",
number: "num"
}[typeof value] ?? "str"
if (key === "language") {
type = "sel"
}
const name = key.split("/").slice(-1)[0]
this.fields.push({name, type, key})
})
}
addHeaders() {
this.fields.forEach(field => {
const th = document.createElement("th")
th.innerText = field.name
this.headers.appendChild(th)
})
}
makeInput(field, value) {
let input = document.createElement("input")
switch (field.type) {
case "num":
input.type = "number"
input.value = value
break
case "str":
input.type = "text"
input.value = value
break
case "bool":
input.type = "checkbox"
input.checked = value
break
case "sel":
input = document.createElement("select")
const options = this.OPTIONS[field.name]
options.forEach(option => {
const opt = document.createElement("option")
opt.innerText = option
opt.value = option
input.appendChild(opt)
})
input.value = value
default:
break
}
return input
}
}
function fetchData(filename) {
fetch("/api/file", {
method: "POST",
body: JSON.stringify({
file: filename
}),
headers: {
"Content-Type": "application/json"
}
}).then(res => {
if (res.ok) {
return res.json()
}
return null
}).then(res => {
if (res !== null) {
displayData(res)
}
})
}
function displayData(data) {
document.getElementById("title").value = data.title
audioTable.showTracks(data.audio_tracks)
subtitleTable.showTracks(data.subtitle_tracks)
}
window.addEventListener("load", () => {
audioTable = new TracksTable(document.getElementById("audio-tracks"))
subtitleTable = new TracksTable(document.getElementById("subtitle-tracks"))
const params = new URLSearchParams(window.location.search)
const file = params.get("f")
document.getElementById("filename").innerText = file
fetchData(file)
})