Tranga-Website/Website/interaction.js

485 lines
17 KiB
JavaScript
Raw Normal View History

let runningJobs = [];
let waitingJobs = [];
2023-08-31 16:45:33 +02:00
let notificationConnectorTypes = [];
let libraryConnectorTypes = [];
2023-09-01 23:43:41 +02:00
let selectedManga;
let selectedJob;
2023-08-31 16:45:33 +02:00
2023-05-31 22:16:14 +02:00
const searchBox = document.querySelector("#searchbox");
const settingsPopup = document.querySelector("#settingsPopup");
2023-05-23 16:27:09 +02:00
const settingsCog = document.querySelector("#settingscog");
const tasksContent = document.querySelector("content");
const createMonitorTaskButton = document.querySelector("#createMonitoJobButton");
const createDownloadChapterTaskButton = document.querySelector("#createDownloadChapterJobButton");
const startJobButton = document.querySelector("#startJobButton");
2023-09-02 15:05:45 +02:00
const cancelJobButton = document.querySelector("#cancelJobButton");
const deleteJobButton = document.querySelector("#deleteJobButton");
2023-09-01 23:43:41 +02:00
const mangaViewerPopup = document.querySelector("#publicationViewerPopup");
const mangaViewerWindow = document.querySelector("publication-viewer");
const mangaViewerDescription = document.querySelector("#publicationViewerDescription");
const mangaViewerName = document.querySelector("#publicationViewerName");
const mangaViewerTags = document.querySelector("#publicationViewerTags");
const mangaViewerAuthor = document.querySelector("#publicationViewerAuthor");
const mangaViewCover = document.querySelector("#pubviewcover");
2023-05-24 20:57:17 +02:00
const settingDownloadLocation = document.querySelector("#downloadLocation");
2023-05-24 21:48:54 +02:00
const settingKomgaUrl = document.querySelector("#komgaUrl");
2023-05-24 20:57:17 +02:00
const settingKomgaUser = document.querySelector("#komgaUsername");
const settingKomgaPass = document.querySelector("#komgaPassword");
2023-06-03 16:25:04 +02:00
const settingKavitaUrl = document.querySelector("#kavitaUrl");
2023-06-03 21:26:29 +02:00
const settingKavitaUser = document.querySelector("#kavitaUsername");
const settingKavitaPass = document.querySelector("#kavitaPassword");
2023-06-15 18:38:47 +02:00
const settingGotifyUrl = document.querySelector("#gotifyUrl");
const settingGotifyAppToken = document.querySelector("#gotifyAppToken");
const settingLunaseaWebhook = document.querySelector("#lunaseaWebhook");
2023-05-24 21:48:54 +02:00
const settingKomgaConfigured = document.querySelector("#komgaConfigured");
2023-06-03 16:25:04 +02:00
const settingKavitaConfigured = document.querySelector("#kavitaConfigured");
2023-06-15 18:38:47 +02:00
const settingGotifyConfigured = document.querySelector("#gotifyConfigured");
const settingLunaseaConfigured = document.querySelector("#lunaseaConfigured");
2023-05-25 10:42:19 +02:00
const settingApiUri = document.querySelector("#settingApiUri");
2023-08-31 23:45:13 +02:00
const newMangaPopup = document.querySelector("#newMangaPopup");
const newMangaConnector = document.querySelector("#newMangaConnector");
const newMangaTitle = document.querySelector("#newMangaTitle");
const newMangaResult = document.querySelector("#newMangaResult");
const newMangaTranslatedLanguage = document.querySelector("#newMangaTranslatedLanguage");
const jobsRunningTag = document.querySelector("#jobsRunningTag");
const jobsQueuedTag = document.querySelector("#jobsQueuedTag");
const loaderdiv = document.querySelector('#loaderdiv');
const jobStatusView = document.querySelector("#jobStatusView");
const jobStatusRunning = document.querySelector("#jobStatusRunning");
const jobStatusWaiting = document.querySelector("#jobStatusWaiting");
2023-08-31 23:45:13 +02:00
function Setup(){
Ping().then((ret) => {
loaderdiv.style.display = 'none';
GetAvailableNotificationConnectors().then((json) => {
json.forEach(connector => {
notificationConnectorTypes[connector.Key] = connector.Value;
});
2023-08-31 23:45:13 +02:00
});
GetAvailableLibraryConnectors().then((json) => {
json.forEach(connector => {
libraryConnectorTypes[connector.Key] = connector.Value;
});
2023-08-31 23:45:13 +02:00
});
GetAvailableControllers().then((json) => {
json.forEach(connector => {
var option = document.createElement('option');
option.value = connector;
option.innerText = connector;
newMangaConnector.appendChild(option);
});
2023-08-31 23:45:13 +02:00
});
UpdateJobs();
setInterval(() => {
UpdateJobs();
}, 1000);
2023-08-31 23:45:13 +02:00
});
}
Setup();
2023-05-24 20:57:41 +02:00
2023-08-31 16:45:33 +02:00
function ResetContent(){
//Delete everything
tasksContent.replaceChildren();
//Add "Add new Task" Button
var add = document.createElement("div");
add.setAttribute("id", "addPublication")
var plus = document.createElement("p");
plus.innerText = "+";
add.appendChild(plus);
2023-08-31 23:45:13 +02:00
add.addEventListener("click", () => ShowNewMangaSearch());
2023-08-31 16:45:33 +02:00
tasksContent.appendChild(add);
2023-05-24 20:57:41 +02:00
}
2023-08-31 23:45:13 +02:00
function ShowNewMangaSearch(){
newMangaTitle.value = "";
newMangaPopup.style.display = "block";
newMangaResult.replaceChildren();
}
newMangaTitle.addEventListener("keypress", (event) => { if(event.key === "Enter") GetNewMangaItems();})
function GetNewMangaItems(){
if(newMangaTitle.value.length < 4)
return;
2023-09-01 23:43:41 +02:00
newMangaResult.replaceChildren();
2023-08-31 23:45:13 +02:00
newMangaConnector.disabled = true;
newMangaTitle.disabled = true;
newMangaTranslatedLanguage.disabled = true;
2023-08-31 23:45:13 +02:00
GetPublicationFromConnector(newMangaConnector.value, newMangaTitle.value).then((json) => {
2023-09-01 23:43:41 +02:00
//console.log(json);
2023-08-31 23:45:13 +02:00
if(json.length > 0)
newMangaResult.style.display = "flex";
json.forEach(result => {
2023-09-01 23:43:41 +02:00
var mangaElement = CreateManga(result, newMangaConnector.value)
newMangaResult.appendChild(mangaElement);
mangaElement.addEventListener("click", (event) => {
ShowMangaWindow(null, result, event, true);
2023-09-01 23:43:41 +02:00
});
2023-08-31 23:45:13 +02:00
});
newMangaConnector.disabled = false;
newMangaTitle.disabled = false;
newMangaTranslatedLanguage.disabled = false;
2023-08-31 23:45:13 +02:00
});
}
2023-08-31 16:45:33 +02:00
//Returns a new "Publication" Item to display in the jobs section
2023-09-01 23:43:41 +02:00
function CreateManga(manga, connector){
var mangaElement = document.createElement('publication');
mangaElement.id = GetValidSelector(manga.internalId);
2023-09-01 23:43:41 +02:00
var mangaImage = document.createElement('img');
mangaImage.src = GetCoverUrl(manga.internalId);
mangaElement.appendChild(mangaImage);
2023-05-23 15:15:29 +02:00
var info = document.createElement('publication-information');
var connectorName = document.createElement('connector-name');
2023-05-23 16:27:09 +02:00
connectorName.innerText = connector;
2023-05-23 15:15:29 +02:00
connectorName.className = "pill";
info.appendChild(connectorName);
2023-09-01 23:43:41 +02:00
var mangaName = document.createElement('publication-name');
mangaName.innerText = manga.sortName;
info.appendChild(mangaName);
mangaElement.appendChild(info);
return mangaElement;
}
createMonitorJobButton.addEventListener("click", () => {
CreateMonitorJob(newMangaConnector.value, selectedManga.internalId, newMangaTranslatedLanguage.value);
UpdateJobs();
2023-09-01 23:43:41 +02:00
mangaViewerPopup.style.display = "none";
});
startJobButton.addEventListener("click", () => {
StartJob(selectedJob.id);
mangaViewerPopup.style.display = "none";
});
2023-09-02 15:05:45 +02:00
cancelJobButton.addEventListener("click", () => {
CancelJob(selectedJob.id);
mangaViewerPopup.style.display = "none";
});
deleteJobButton.addEventListener("click", () => {
RemoveJob(selectedJob.id);
2023-09-01 23:43:41 +02:00
UpdateJobs();
mangaViewerPopup.style.display = "none";
});
2023-05-23 15:15:29 +02:00
function ShowMangaWindow(job, manga, event, add){
2023-09-01 23:43:41 +02:00
selectedManga = manga;
selectedJob = job;
//Show popup
2023-09-01 23:43:41 +02:00
mangaViewerPopup.style.display = "block";
2023-05-24 20:17:50 +02:00
//Set position to mouse-position
2023-09-01 23:43:41 +02:00
if(event.clientY < window.innerHeight - mangaViewerWindow.offsetHeight)
mangaViewerWindow.style.top = `${event.clientY}px`;
else
2023-09-01 23:43:41 +02:00
mangaViewerWindow.style.top = `${event.clientY - mangaViewerWindow.offsetHeight}px`;
2023-09-01 23:43:41 +02:00
if(event.clientX < window.innerWidth - mangaViewerWindow.offsetWidth)
mangaViewerWindow.style.left = `${event.clientX}px`;
else
2023-09-01 23:43:41 +02:00
mangaViewerWindow.style.left = `${event.clientX - mangaViewerWindow.offsetWidth}px`;
2023-05-23 17:57:48 +02:00
2023-05-24 20:17:50 +02:00
//Edit information inside the window
2023-09-01 23:43:41 +02:00
mangaViewerName.innerText = manga.sortName;
mangaViewerTags.innerText = manga.tags.join(", ");
mangaViewerDescription.innerText = manga.description;
mangaViewerAuthor.innerText = manga.authors.join(',');
mangaViewCover.src = GetCoverUrl(manga.internalId);
toEditId = manga.internalId;
2023-05-23 17:57:48 +02:00
2023-05-24 20:17:50 +02:00
//Check what action should be listed
2023-05-23 18:28:27 +02:00
if(add){
createMonitorJobButton.style.display = "initial";
2023-09-02 22:15:48 +02:00
createDownloadChapterJobButton.style.display = "none";
2023-09-02 15:05:45 +02:00
cancelJobButton.style.display = "none";
startJobButton.style.display = "none";
deleteJobButton.style.display = "none";
2023-05-23 18:28:27 +02:00
}
2023-05-23 18:46:06 +02:00
else{
createMonitorJobButton.style.display = "none";
createDownloadChapterJobButton.style.display = "none";
2023-09-02 15:05:45 +02:00
cancelJobButton.style.display = "initial";
startJobButton.style.display = "initial";
deleteJobButton.style.display = "initial";
2023-05-23 18:46:06 +02:00
}
2023-05-23 17:57:48 +02:00
}
2023-05-24 20:17:50 +02:00
function HidePublicationPopup(){
publicationViewerPopup.style.display = "none";
}
2023-08-31 16:45:33 +02:00
searchBox.addEventListener("keyup", () => FilterResults());
//Filter shown jobs
2023-05-31 22:16:14 +02:00
function FilterResults(){
if(searchBox.value.length > 0){
tasksContent.childNodes.forEach(publication => {
publication.childNodes.forEach(item => {
if(item.nodeName.toLowerCase() == "publication-information"){
item.childNodes.forEach(information => {
if(information.nodeName.toLowerCase() == "publication-name"){
if(!information.textContent.toLowerCase().includes(searchBox.value.toLowerCase())){
publication.style.display = "none";
}else{
publication.style.display = "initial";
}
}
});
}
});
});
}else{
tasksContent.childNodes.forEach(publication => publication.style.display = "initial");
}
}
2023-08-31 16:45:33 +02:00
settingsCog.addEventListener("click", () => {
OpenSettings();
settingsPopup.style.display = "flex";
});
2023-08-31 16:45:33 +02:00
settingKomgaUrl.addEventListener("keypress", (event) => { { if(event.key === "Enter") UpdateSettings(); } });
settingKomgaUser.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
settingKomgaPass.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
settingKavitaUrl.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
settingKavitaUser.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
settingKavitaPass.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
settingGotifyUrl.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
settingGotifyAppToken.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
settingLunaseaWebhook.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
settingApiUri.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
2023-08-31 16:45:33 +02:00
function OpenSettings(){
settingGotifyConfigured.innerText = "❌";
settingLunaseaConfigured.innerText = "❌";
settingKavitaConfigured.innerText = "❌";
settingKomgaConfigured.innerText = "❌";
settingKomgaUrl.value = "";
settingKomgaUser.value = "";
settingKomgaPass.value = "";
settingKavitaUrl.value = "";
settingKavitaUser.value = "";
settingKavitaPass.value = "";
settingGotifyUrl.value = "";
settingGotifyAppToken.value = "";
settingLunaseaWebhook.value = "";
settingApiUri.value = "";
GetSettings().then((json) => {
//console.log(json);
settingDownloadLocation.innerText = json.downloadLocation;
settingApiUri.placeholder = apiUri;
});
GetLibraryConnectors().then((json) => {
//console.log(json);
json.forEach(connector => {
switch(libraryConnectorTypes[connector.libraryType]){
case "Kavita":
settingKavitaConfigured.innerText = "✅";
settingKavitaUrl.placeholder = connector.baseUrl;
settingKavitaUser.placeholder = "***";
settingKavitaPass.placeholder = "***";
break;
case "Komga":
settingKomgaConfigured.innerText = "✅";
settingKomgaUrl.placeholder = connector.baseUrl;
settingKomgaUser.placeholder = "***";
settingKomgaPass.placeholder = "***";
break;
default:
console.log("Unknown type");
console.log(connector);
break;
}
});
});
GetNotificationConnectors().then((json) => {
//console.log(json);
json.forEach(connector => {
switch(notificationConnectorTypes[connector.notificationConnectorType]){
case "Gotify":
settingGotifyUrl.placeholder = connector.endpoint;
settingGotifyAppToken.placeholder = "***";
settingGotifyConfigured.innerText = "✅";
break;
case "LunaSea":
settingLunaseaConfigured.innerText = "✅";
settingLunaseaWebhook.placeholder = connector.id;
break;
default:
console.log("Unknown type");
console.log(connector);
break;
}
});
});
}
2023-08-31 16:45:33 +02:00
function UpdateSettings(){
if(settingApiUri.value != ""){
apiUri = settingApiUri.value;
setCookie("apiUri", apiUri);
Setup();
}
if(settingKomgaUrl.value != "" &&
settingKomgaUser.value != "" &&
settingKomgaPass.value != ""){
UpdateKomga(settingKomgaUrl.value, utf8_to_b64(`${settingKomgaUser.value}:${settingKomgaPass.value}`));
}
if(settingKavitaUrl.value != "" &&
settingKavitaUser.value != "" &&
settingKavitaPass.value != ""){
UpdateKavita(settingKavitaUrl.value, settingKavitaUser.value, settingKavitaPass.value);
}
if(settingGotifyUrl.value != "" &&
settingGotifyAppToken.value != ""){
UpdateGotify(settingGotifyUrl.value, settingGotifyAppToken.value);
}
if(settingLunaseaWebhook.value != ""){
UpdateLunaSea(settingLunaseaWebhook.value);
}
OpenSettings();
Setup();
2023-05-31 22:16:14 +02:00
}
2023-08-31 16:45:33 +02:00
function utf8_to_b64(str) {
return window.btoa(unescape(encodeURIComponent( str )));
}
2023-09-01 23:43:41 +02:00
function UpdateJobs(){
GetMonitorJobs().then((json) => {
ResetContent();
//console.log(json);
2023-09-01 23:43:41 +02:00
json.forEach(job => {
var mangaView = CreateManga(job.manga, job.mangaConnector.name);
mangaView.addEventListener("click", (event) => {
ShowMangaWindow(job, job.manga, event, false);
2023-09-01 23:43:41 +02:00
});
tasksContent.appendChild(mangaView);
});
});
GetWaitingJobs().then((json) => {
jobsQueuedTag.innerText = json.length;
var nowWaitingJobs = [];
json.forEach(job => {
if(!waitingJobs.includes(GetValidSelector(job.id))){
var jobDom = createJob(job);
jobStatusWaiting.appendChild(jobDom);
}
nowWaitingJobs.push(GetValidSelector(job.id));
});
waitingJobs = nowWaitingJobs;
});
jobStatusWaiting.childNodes.forEach(child => {
if(!waitingJobs.includes(child.id))
jobStatusWaiting.removeChild(child);
});
GetRunningJobs().then((json) => {
jobsRunningTag.innerText = json.length;
var nowRunningJobs = [];
json.forEach(job => {
if(!runningJobs.includes(GetValidSelector(job.id))){
var jobDom = createJob(job);
jobStatusRunning.appendChild(jobDom);
}
nowRunningJobs.push(GetValidSelector(job.id));
UpdateJobProgress(job.id);
});
runningJobs = nowRunningJobs;
});
jobStatusRunning.childNodes.forEach(child => {
if(!runningJobs.includes(child.id))
jobStatusRunning.removeChild(child);
});
2023-09-01 23:43:41 +02:00
}
function createJob(jobjson){
var manga;
if(jobjson.chapter != null)
manga = jobjson.chapter.parentManga;
else if(jobjson.manga != null)
manga = jobjson.manga;
else return null;
var wrapper = document.createElement("div");
wrapper.className = "jobWrapper";
wrapper.id = GetValidSelector(jobjson.id);
var image = document.createElement("img");
image.className = "jobImage";
image.src = GetCoverUrl(manga.internalId);
wrapper.appendChild(image);
var title = document.createElement("span");
title.className = "jobTitle";
if(jobjson.chapter != null)
title.innerText = `${manga.sortName} - ${jobjson.chapter.fileName}`;
else if(jobjson.manga != null)
title.innerText = manga.sortName;
wrapper.appendChild(title);
var progressBar = document.createElement("progress");
progressBar.className = "jobProgressBar";
progressBar.id = `jobProgressBar${GetValidSelector(jobjson.id)}`;
wrapper.appendChild(progressBar);
var progressSpan = document.createElement("span");
progressSpan.className = "jobProgressSpan";
progressSpan.id = `jobProgressSpan${GetValidSelector(jobjson.id)}`;
progressSpan.innerText = "0% 00:00:00";
wrapper.appendChild(progressSpan);
var cancelSpan = document.createElement("span");
cancelSpan.className = "jobCancel";
cancelSpan.innerText = "Cancel";
cancelSpan.addEventListener("click", () => CancelJob(jobjson.id));
wrapper.appendChild(cancelSpan);
return wrapper;
}
function ShowJobQueue(){
jobStatusView.style.display = "initial";
}
function UpdateJobProgress(jobId){
GetProgress(jobId).then((json) => {
var progressBar = document.querySelector(`#jobProgressBar${GetValidSelector(jobId)}`);
var progressSpan = document.querySelector(`#jobProgressSpan${GetValidSelector(jobId)}`);
if(progressBar != null && json.progress != 0){
progressBar.value = json.progress;
}
if(progressSpan != null){
var percentageStr = "0%";
var timeleftStr = "00:00:00";
if(json.progress != 0){
percentageStr = Intl.NumberFormat("en-US", { style: "percent"}).format(json.progress);
timeleftStr = json.timeRemaining.split('.')[0];
}
progressSpan.innerText = `${percentageStr} ${timeleftStr}`;
}
});
}
function GetValidSelector(str){
var clean = [...str.matchAll(/[a-zA-Z0-9]*-*_*/g)];
return clean.join('');
}