458 lines
15 KiB
JavaScript

"use strict";
class App {
lang;
tls;
config;
parserList;
uploadableFiles;
wrap;
actionsArea;
aside;
main;
generateTextElement(type, value) {
const elem = document.createElement(type);
elem.textContent = value;
return elem;
}
generateLabelInput(id, labelText, explanationText, type, value) {
const output = document.createElement("div");
output.classList.add("label-input");
const label = document.createElement("label");
label.textContent = labelText;
label.setAttribute("for", id);
output.appendChild(label);
const input = document.createElement("input");
input.id = id;
input.type = "text";
input.value = value;
output.appendChild(input);
const help = document.createElement("span");
help.classList.add("icon-help");
help.title = explanationText;
output.appendChild(help);
return {'wrap': output, 'input': input};
}
async generateSidebar() {
this.aside.appendChild(this.generateTextElement("h2", this.tls.settings)); // TODO
// Set up fields
const instanceLinkArea = this.generateLabelInput("instance-link",
this.tls.instance_link, this.tls.instance_link_explica, "url", this.config.settings.instance);
this.aside.appendChild(instanceLinkArea.wrap);
const usernameArea = this.generateLabelInput("username",
this.tls.username, this.tls.username_explica, "text", this.config.settings.username);
this.aside.appendChild(usernameArea.wrap);
const mailArea = this.generateLabelInput("mail",
this.tls.mail, this.tls.mail_explica, "email", this.config.settings.mail);
this.aside.appendChild(mailArea.wrap);
const institutionIdArea = this.generateLabelInput("institutionId",
this.tls.institution_id, this.tls.institution_id_explica, "number", this.config.settings.institution_id);
this.aside.appendChild(institutionIdArea.wrap);
const tokenArea = this.generateLabelInput("token",
this.tls.token, this.tls.token_explica, "text", this.config.settings.token);
this.aside.appendChild(tokenArea.wrap);
const parserDiv = document.createElement("div");
parserDiv.classList.add("label-input");
const parserLabel = document.createElement("label");
parserLabel.setAttribute("for", "parserSelect");
parserLabel.textContent = this.tls.parser;
parserDiv.appendChild(parserLabel);
const parserSelect = document.createElement("select");
parserSelect.id = "parserSelect";
for (const entry of this.parserList) {
const opt = document.createElement("option");
opt.value = entry.title;
opt.textContent = entry.title;
if (entry.title === this.config.settings.parser) {
opt.setAttribute("selected", "selected");
}
parserSelect.appendChild(opt);
}
parserDiv.appendChild(parserSelect);
const parserHelp = document.createElement("span");
parserHelp.classList.add("icon-help");
parserHelp.title = this.tls.parser_explica;
parserDiv.appendChild(parserHelp);
this.aside.appendChild(parserDiv);
const uploadFolderArea = this.generateLabelInput("upload-folder",
this.tls.upload_directory, this.tls.upload_directory_explica, "text", this.config.settings.upload_directory);
this.aside.appendChild(uploadFolderArea.wrap);
const visibleDivOuter = document.createElement("div");
visibleDivOuter.classList.add("label-input");
const visibleLabel = document.createElement("label");
visibleLabel.setAttribute("for", "visible");
visibleLabel.textContent = this.tls.publish_immediately;
visibleDivOuter.appendChild(visibleLabel);
const visibleDiv = document.createElement("div");
const visibleSwitch = document.createElement("div");
visibleSwitch.classList.add("switch");
const visibleInput = document.createElement("input");
visibleInput.type = "checkbox";
if (this.config.settings.visible === true) {
visibleInput.checked = "checked";
console.log(visibleInput);
}
visibleSwitch.appendChild(visibleInput);
const visibleSlider = document.createElement("span");
visibleSlider.classList.add("slider");
visibleSlider.addEventListener('click', function() {
visibleInput.checked = !visibleInput.checked;
console.log(visibleInput);
});
visibleSwitch.appendChild(visibleSlider);
visibleDiv.appendChild(visibleSwitch);
visibleDivOuter.appendChild(visibleDiv);
const visibleHelp = document.createElement("span");
visibleHelp.classList.add("icon-help");
visibleHelp.title = this.tls.publish_immediately_explica;
visibleDivOuter.appendChild(visibleHelp);
this.aside.appendChild(visibleDivOuter);
// Additional settings
this.aside.appendChild(this.generateTextElement("h3", this.tls.additional_settings));
const addSettingsArea = document.createElement("div");
const app = this;
function generateAdditionalSettingsField(key, value) {
const line = document.createElement("div");
line.classList.add("label-input");
const newKey = document.createElement("input");
newKey.placeholder = app.tls.add_settings_key;
newKey.required = "required";
newKey.value = key;
line.appendChild(newKey);
const newVal = document.createElement("input");
newVal.placeholder = app.tls.add_settings_value;
newVal.required = "required";
newVal.value = value;
line.appendChild(newVal);
const removeB = document.createElement("button");
removeB.textContent = " x ";
removeB.title = app.tls.remove;
line.appendChild(removeB);
removeB.addEventListener('click', function() {
line.parentElement.removeChild(line);
});
return line;
}
if (this.config.settings.settings != undefined && this.config.settings.settings != null && this.config.settings.settings.length != 0) {
for (let settingKey in this.config.settings.settings) {
addSettingsArea.appendChild(generateAdditionalSettingsField(settingKey, this.config.settings.settings[settingKey]));
}
}
this.aside.appendChild(addSettingsArea);
const newSettingLine = document.createElement("form");
newSettingLine.classList.add("label-input");
const newKey = document.createElement("input");
newKey.placeholder = this.tls.add_settings_key;
newKey.required = "required";
newSettingLine.appendChild(newKey);
const newVal = document.createElement("input");
newVal.placeholder = this.tls.add_settings_value;
newVal.required = "required";
newSettingLine.appendChild(newVal);
const newSubmitB = document.createElement("button");
newSubmitB.type = "submit";
newSubmitB.textContent = " > ";
newSubmitB.title = app.tls.add;
newSettingLine.appendChild(newSubmitB);
newSettingLine.addEventListener('submit', function(e) {
e.preventDefault();
e.stopPropagation();
addSettingsArea.appendChild(generateAdditionalSettingsField(newKey.value, newVal.value));
newKey.value = "";
newVal.value = "";
});
this.aside.appendChild(newSettingLine)
const updateB = document.createElement("button");
updateB.textContent = this.tls.save_update;
updateB.classList.add("updateB");
this.aside.appendChild(updateB);
updateB.addEventListener('click', async function() {
let toSave = {
instance: instanceLinkArea.input.value,
username: usernameArea.input.value,
mail: mailArea.input.value,
token: tokenArea.input.value,
institution_id: parseInt(institutionIdArea.input.value),
parser: parserSelect.value,
upload_directory: uploadFolderArea.input.value,
visible: visibleInput.checked,
settings: {}
};
for (const l of addSettingsArea.children) {
toSave.settings[l.children[0].value] = l.children[1].value;
}
const response = await window.fetch('/update-settings', {
method: 'POST', cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: "settings=" + encodeURIComponent(JSON.stringify(toSave, null, 2))
});
if (!response.ok) {
console.log("Failed to save");
window.alert("Failed to store.");
}
const json = await response.json();
if (json.success === true) {
location.reload();
}
else {
alert("Error:\n" + json.error);
}
});
}
generateMain() {
this.main.appendChild(this.generateTextElement("h2", this.tls.uploadable_files));
// Metadata
const metadataSec = document.createElement("section");
metadataSec.appendChild(this.generateTextElement("h3", this.tls.metadata_files));
const metadataList = document.createElement("div");
metadataList.classList.add("upload-file-list");
for (const filename of this.uploadableFiles.metadata) {
const fileline = document.createElement("span");
fileline.classList.add("icon-file");
fileline.textContent = filename;
metadataList.appendChild(fileline);
}
metadataSec.appendChild(metadataList);
this.main.appendChild(metadataSec);
// Media
const mediaSec = document.createElement("section");
mediaSec.appendChild(this.generateTextElement("h3", this.tls.media_files));
const mediaList = document.createElement("div");
mediaList.classList.add("upload-file-list");
for (const filename of this.uploadableFiles.media_files) {
const fileline = document.createElement("span");
fileline.classList.add("icon-file");
fileline.textContent = filename;
mediaList.appendChild(fileline);
}
mediaSec.appendChild(mediaList);
this.main.appendChild(mediaSec);
}
generateActionsMenu() {
if (this.uploadableFiles.metadata.length === 0 && this.uploadableFiles.media_files.length === 0) {
return false;
}
const uploadTrigger = document.createElement("span");
uploadTrigger.textContent = this.tls.upload;
this.actionsArea.appendChild(uploadTrigger);
const app = this;
uploadTrigger.addEventListener('click', function() {
const transferOverlay = document.createElement("div");
transferOverlay.id = "transfer-overlay";
transferOverlay.classList.add("transfer-overlay");
const hl = document.createElement("div");
hl.classList.add("transfer-overlay-hl");
hl.appendChild(app.generateTextElement("h3", app.tls.upload));
const closeB = document.createElement("span");
closeB.classList.add("overlay-close");
hl.appendChild(closeB);
closeB.addEventListener('click', function() { location.reload(); });
// closeB.addEventListener('click', function() { transferOverlay.parentElement.removeChild(transferOverlay); });
transferOverlay.appendChild(hl);
const transferMsgs = document.createElement("div");
transferMsgs.classList.add("transfer-msgs");
transferOverlay.appendChild(transferMsgs);
app.wrap.appendChild(transferOverlay);
const iframe = document.createElement("iframe");
iframe.src = "/trigger-upload";
transferOverlay.appendChild(iframe);
}, {once: true});
}
// Provides a sidebar entry for describing the parser
generateParserDesc() {
for (const parser of this.parserList) {
if (parser.title == this.config.settings.parser) {
const aside = document.createElement("div");
aside.classList.add("sec-aside");
aside.appendChild(this.generateTextElement("h3", this.tls.parser));
const div = document.createElement("div");
div.classList.add("parser-desc");
const desc = document.createElement("p");
desc.textContent = parser.comment;
div.appendChild(desc);
aside.appendChild(div);
this.wrap.appendChild(aside);
break;
}
}
}
render() {
if (this.config.setup_required === true) {
wrap.classList.add("one-column");
this.generateSidebar();
}
else {
this.generateSidebar();
this.generateMain();
this.generateActionsMenu();
this.generateParserDesc();
}
}
setupFromApis() {
const app = this;
let done = 0;
function wrapFinish() {
if (done === 4) {
app.render();
}
}
window.fetch('/get-settings', {method: 'GET', cache: 'no-cache', credentials: 'same-origin'})
.then(function(response) { return response.json(); })
.then(function(elements) {
app.config = elements;
done++;
wrapFinish();
});
window.fetch('/list-parsers', {method: 'GET', cache: 'no-cache', credentials: 'same-origin'})
.then(function(response) { return response.json(); })
.then(function(elements) {
app.parserList = elements;
done++;
wrapFinish();
});
window.fetch('/list-uploadable', {method: 'GET', cache: 'no-cache', credentials: 'same-origin'})
.then(function(response) { return response.json(); })
.then(function(elements) {
app.uploadableFiles = elements;
done++;
wrapFinish();
});
window.fetch('/get-translations?lang=' + encodeURIComponent(this.lang), {method: 'GET', cache: 'no-cache', credentials: 'same-origin'})
.then(function(response) { return response.json(); })
.then(function(elements) {
app.tls = elements.webdav_uploader;
done++;
wrapFinish();
});
}
constructor() {
this.wrap = document.getElementById("wrap");
this.lang = navigator.language.substring(0, 2)
if (["de", "en"].includes(this.lang) === false) {
this.lang = "en";
}
this.aside = document.createElement("aside");
this.main = document.createElement("main");
this.actionsArea = document.getElementById("actions");
this.wrap.appendChild(this.aside);
this.wrap.appendChild(this.main);
this.setupFromApis();
}
}
new App();