Complete rewrite #2
123
README.md
Normal file
123
README.md
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
<!-- PROJECT SHIELDS -->
|
||||||
|
<!--
|
||||||
|
*** I'm using markdown "reference style" links for readability.
|
||||||
|
*** Reference links are enclosed in brackets [ ] instead of parentheses ( ).
|
||||||
|
*** See the bottom of this document for the declaration of the reference variables
|
||||||
|
*** for contributors-url, forks-url, etc. This is an optional, concise syntax you may use.
|
||||||
|
*** https://www.markdownguide.org/basic-syntax/#reference-style-links
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- PROJECT LOGO -->
|
||||||
|
<br />
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
<h3 align="center">Tranga-Website</h3>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
Automatic Manga and Metadata downloader
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
This is the Website for <a href="https://github.com/C9Glax/tranga">Tranga</a> (API)
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- TABLE OF CONTENTS -->
|
||||||
|
<details>
|
||||||
|
<summary>Table of Contents</summary>
|
||||||
|
<ol>
|
||||||
|
<li>
|
||||||
|
<a href="#about-the-project">About The Project</a>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#built-with">Built With</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="#getting-started">Getting Started</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="#roadmap">Roadmap</a></li>
|
||||||
|
<li><a href="#contributing">Contributing</a></li>
|
||||||
|
<li><a href="#license">License</a></li>
|
||||||
|
<li><a href="#acknowledgments">Acknowledgments</a></li>
|
||||||
|
</ol>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ABOUT THE PROJECT -->
|
||||||
|
## About The Project
|
||||||
|
|
||||||
|
Tranga-Website is the Web-frontend to [Tranga](https://github.com/C9Glax/tranga) (the API). It displays information aquired from Tranga and can create Jobs (Manga-Downloads).
|
||||||
|
|
||||||
|
### What this does do (and nothing else)
|
||||||
|
|
||||||
|
This repo makes HTTP-requests to the [Tranga-API](https://github.com/C9Glax/tranga) to display it's present configuration.
|
||||||
|
|
||||||
|
### Built With
|
||||||
|
|
||||||
|
- nginx
|
||||||
|
- HTML, CSS, and barebones Javascript
|
||||||
|
- 💙 Blåhaj 🦈
|
||||||
|
|
||||||
|
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
||||||
|
|
||||||
|
<!-- GETTING STARTED -->
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
There is a single release:
|
||||||
|
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
|
Download [docker-compose.yaml](https://github.com/C9Glax/tranga-website/blob/cuttingedge/docker-compose.yaml) and configure to your needs.
|
||||||
|
The `docker-compose` also includes [Tranga](https://github.com/C9Glax/tranga) as backend. For its configuration refer to the repo README.
|
||||||
|
|
||||||
|
<!-- ROADMAP -->
|
||||||
|
## Roadmap
|
||||||
|
|
||||||
|
- [ ] ❓
|
||||||
|
|
||||||
|
See the [open issues](https://github.com/C9Glax/tranga-website/issues) for a full list of proposed features (and known issues).
|
||||||
|
|
||||||
|
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- CONTRIBUTING -->
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
The following is copy & pasted:
|
||||||
|
|
||||||
|
Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
|
||||||
|
|
||||||
|
If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement".
|
||||||
|
Don't forget to give the project a star! Thanks again!
|
||||||
|
|
||||||
|
1. Fork the Project
|
||||||
|
2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
|
||||||
|
3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
|
||||||
|
4. Push to the Branch (`git push origin feature/AmazingFeature`)
|
||||||
|
5. Open a Pull Request
|
||||||
|
|
||||||
|
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- LICENSE -->
|
||||||
|
## License
|
||||||
|
|
||||||
|
Distributed under the GNU GPLv3 License. See `LICENSE.txt` for more information.
|
||||||
|
|
||||||
|
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- ACKNOWLEDGMENTS -->
|
||||||
|
## Acknowledgments
|
||||||
|
|
||||||
|
* [Choose an Open Source License](https://choosealicense.com)
|
||||||
|
* [Font Awesome](https://fontawesome.com)
|
||||||
|
* [Best-README-Template](https://github.com/othneildrew/Best-README-Template/tree/master)
|
||||||
|
|
||||||
|
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
BIN
Screenshots/Screenshot 2023-09-08 at 20-03-13 Tranga.png
Normal file
BIN
Screenshots/Screenshot 2023-09-08 at 20-03-13 Tranga.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 162 KiB |
BIN
Screenshots/Screenshot 2023-09-08 at 20-03-37 Tranga.png
Normal file
BIN
Screenshots/Screenshot 2023-09-08 at 20-03-37 Tranga.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 356 KiB |
BIN
Screenshots/Screenshot 2023-09-08 at 20-03-45 Tranga.png
Normal file
BIN
Screenshots/Screenshot 2023-09-08 at 20-03-45 Tranga.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 MiB |
BIN
Screenshots/Screenshot 2023-09-08 at 20-03-58 Tranga.png
Normal file
BIN
Screenshots/Screenshot 2023-09-08 at 20-03-58 Tranga.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 MiB |
BIN
Screenshots/Screenshot 2023-09-08 at 20-04-41 Tranga.png
Normal file
BIN
Screenshots/Screenshot 2023-09-08 at 20-04-41 Tranga.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 MiB |
@ -3,6 +3,15 @@
|
|||||||
if(getCookie("apiUri") != ""){
|
if(getCookie("apiUri") != ""){
|
||||||
apiUri = getCookie("apiUri");
|
apiUri = getCookie("apiUri");
|
||||||
}
|
}
|
||||||
|
setCookie("apiUri", apiUri);
|
||||||
|
|
||||||
|
function setCookie(cname, cvalue) {
|
||||||
|
const d = new Date();
|
||||||
|
d.setTime(d.getTime() + (365*24*60*60*1000));
|
||||||
|
let expires = "expires="+ d.toUTCString();
|
||||||
|
document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/;samesite=strict";
|
||||||
|
}
|
||||||
|
|
||||||
function getCookie(cname) {
|
function getCookie(cname) {
|
||||||
let name = cname + "=";
|
let name = cname + "=";
|
||||||
let decodedCookie = decodeURIComponent(document.cookie);
|
let decodedCookie = decodeURIComponent(document.cookie);
|
||||||
@ -42,127 +51,144 @@ function DeleteData(uri){
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function Ping(){
|
||||||
|
let ret = await GetData(`${apiUri}/Ping`);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
async function GetAvailableControllers(){
|
async function GetAvailableControllers(){
|
||||||
var uri = apiUri + "/Connectors";
|
var uri = apiUri + "/Connectors";
|
||||||
let json = await GetData(uri);
|
let json = await GetData(uri);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetPublicationFromConnector(connectorName, title){
|
async function GetPublicationFromConnector(connector, title){
|
||||||
var uri = apiUri + `/Publications/FromConnector?connectorName=${connectorName}&title=${title}`;
|
var uri;
|
||||||
|
if(title.includes("http")){
|
||||||
|
uri = `${apiUri}/Manga/FromConnector?connector=${connector}&url=${title}`;
|
||||||
|
}else{
|
||||||
|
uri = `${apiUri}/Manga/FromConnector?connector=${connector}&title=${title}`;
|
||||||
|
}
|
||||||
|
let json = await GetData(uri);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function GetChapters(connector, internalId, language){
|
||||||
|
var uri = `${apiUri}/Manga/Chapters?connector=${connector}&internalId=${internalId}&translatedLanguage=${language}`;
|
||||||
let json = await GetData(uri);
|
let json = await GetData(uri);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetKnownPublications(){
|
function GetCoverUrl(internalId){
|
||||||
var uri = apiUri + "/Publications/Known";
|
return `${apiUri}/Manga/Cover?internalId=${internalId}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function GetAllJobs(){
|
||||||
|
var uri = `${apiUri}/Jobs`;
|
||||||
|
let json = await GetData(uri);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function GetRunningJobs(){
|
||||||
|
var uri = `${apiUri}/Jobs/Running`;
|
||||||
let json = await GetData(uri);
|
let json = await GetData(uri);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetPublication(internalId){
|
async function GetWaitingJobs(){
|
||||||
var uri = apiUri + `/Publications/Known?internalId=${internalId}`;
|
var uri = `${apiUri}/Jobs/Waiting`;
|
||||||
let json = await GetData(uri);
|
let json = await GetData(uri);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetChapters(internalId, connectorName, onlyNew, language){
|
async function GetMonitorJobs(){
|
||||||
var uri = apiUri + `/Publications/Chapters?internalId=${internalId}&connectorName=${connectorName}&onlyNew=${onlyNew}&language=${language}`;
|
var uri = `${apiUri}/Jobs/MonitorJobs`;
|
||||||
let json = await GetData(uri);
|
let json = await GetData(uri);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetTaskTypes(){
|
async function GetProgress(jobId){
|
||||||
var uri = apiUri + "/Tasks/Types";
|
var uri = `${apiUri}/Jobs/Progress?jobId=${jobId}`;
|
||||||
let json = await GetData(uri);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
async function GetRunningTasks(){
|
|
||||||
var uri = apiUri + "/Tasks/RunningTasks";
|
|
||||||
let json = await GetData(uri);
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function GetDownloadTasks(){
|
|
||||||
var uri = apiUri + "/Tasks?taskType=MonitorPublication";
|
|
||||||
let json = await GetData(uri);
|
let json = await GetData(uri);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetSettings(){
|
async function GetSettings(){
|
||||||
var uri = apiUri + "/Settings";
|
var uri = `${apiUri}/Settings`;
|
||||||
let json = await GetData(uri);
|
let json = await GetData(uri);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function GetKomgaTask(){
|
async function GetAvailableNotificationConnectors(){
|
||||||
var uri = apiUri + "/Tasks?taskType=UpdateLibraries";
|
var uri = `${apiUri}/NotificationConnectors/Types`;
|
||||||
let json = await GetData(uri);
|
let json = await GetData(uri);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
function CreateMonitorTask(connectorName, internalId, reoccurrence, language){
|
async function GetNotificationConnectors(){
|
||||||
var uri = apiUri + `/Tasks/CreateMonitorTask?connectorName=${connectorName}&internalId=${internalId}&reoccurrenceTime=${reoccurrence}&language=${language}`;
|
var uri = `${apiUri}/NotificationConnectors`;
|
||||||
|
let json = await GetData(uri);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function GetAvailableLibraryConnectors(){
|
||||||
|
var uri = `${apiUri}/LibraryConnectors/Types`;
|
||||||
|
let json = await GetData(uri);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function GetLibraryConnectors(){
|
||||||
|
var uri = `${apiUri}/LibraryConnectors`;
|
||||||
|
let json = await GetData(uri);
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
|
||||||
|
function CreateMonitorJob(connector, internalId, language){
|
||||||
|
var uri = `${apiUri}/Jobs/MonitorManga?connector=${connector}&internalId=${internalId}&interval=03:00:00&translatedLanguage=${language}`;
|
||||||
PostData(uri);
|
PostData(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CreateDownloadChaptersTask(connectorName, internalId, chapters, language){
|
function CreateDownloadNewChaptersJob(connector, internalId, language){
|
||||||
var uri = apiUri + `/Tasks/CreateDownloadChaptersTask?connectorName=${connectorName}&internalId=${internalId}&chapters=${chapters}&language=${language}`;
|
var uri = `${apiUri}/Jobs/DownloadNewChapters?connector=${connector}&internalId=${internalId}&translatedLanguage=${language}`;
|
||||||
PostData(uri);
|
PostData(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
function StartTask(taskType, connectorName, internalId){
|
function StartJob(jobId){
|
||||||
var uri = apiUri + `/Tasks/Start?taskType=${taskType}&connectorName=${connectorName}&internalId=${internalId}`;
|
var uri = `${apiUri}/Jobs/StartNow?jobId=${jobId}`;
|
||||||
PostData(uri);
|
|
||||||
}
|
|
||||||
|
|
||||||
function EnqueueTask(taskType, connectorName, publicationId){
|
|
||||||
var uri = apiUri + `/Queue/Enqueue?taskType=${taskType}&connectorName=${connectorName}&publicationId=${publicationId}`;
|
|
||||||
PostData(uri);
|
PostData(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
function UpdateDownloadLocation(downloadLocation){
|
function UpdateDownloadLocation(downloadLocation){
|
||||||
var uri = apiUri + "/Settings/Update?"
|
var uri = `${apiUri}/Settings/UpdateDownloadLocation?downloadLocation=${downloadLocation}`;
|
||||||
uri += "&downloadLocation="+downloadLocation;
|
PostData(uri);
|
||||||
PostData(uri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function UpdateKomga(komgaUrl, komgaAuth){
|
function UpdateKomga(komgaUrl, komgaAuth){
|
||||||
var uri = apiUri + "/Settings/Update?"
|
var uri = `${apiUri}/LibraryConnectors/Update?libraryConnector=Komga&komgaUrl=${komgaUrl}&komgaAuth=${komgaAuth}`;
|
||||||
uri += `&komgaUrl=${komgaUrl}&komgaAuth=${komgaAuth}`;
|
|
||||||
PostData(uri);
|
PostData(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
function UpdateKavita(kavitaUrl, kavitaUser, kavitaPass){
|
function UpdateKavita(kavitaUrl, kavitaUsername, kavitaPassword){
|
||||||
var uri = apiUri + "/Settings/Update?"
|
var uri = `${apiUri}/LibraryConnectors/Update?libraryConnector=Kavita&kavitaUrl=${kavitaUrl}&kavitaUsername=${kavitaUsername}&kavitaPassword={kavitaPassword}`;
|
||||||
uri += `&kavitaUrl=${kavitaUrl}&kavitaUsername=${kavitaUser}&kavitaPassword=${kavitaPass}`;
|
|
||||||
PostData(uri);
|
PostData(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
function UpdateGotify(gotifyUrl, gotifyAppToken){
|
function UpdateGotify(gotifyUrl, gotifyAppToken){
|
||||||
var uri = apiUri + "/Settings/Update?"
|
var uri = `${apiUri}/NotificationConnectors/Update?notificationConnector=Gotify&gotifyUrl=${gotifyUrl}&gotifyAppToken=${gotifyAppToken}`;
|
||||||
uri += `&gotifyUrl=${gotifyUrl}&gotifyAppToken=${gotifyAppToken}`;
|
|
||||||
PostData(uri);
|
PostData(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
function UpdateLunaSea(lunaseaWebhook){
|
function UpdateLunaSea(lunaseaWebhook){
|
||||||
var uri = apiUri + "/Settings/Update?"
|
var uri = `${apiUri}/NotificationConnectors/Update?notificationConnector=LunaSea&lunaseaWebhook=${lunaseaWebhook}`;
|
||||||
uri += `&lunaseaWebhook=${lunaseaWebhook}`;
|
|
||||||
PostData(uri);
|
PostData(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DeleteTask(taskType, connectorName, publicationId){
|
function RemoveJob(jobId){
|
||||||
var uri = apiUri + `/Tasks?taskType=${taskType}&connectorName=${connectorName}&publicationId=${publicationId}`;
|
var uri = `${apiUri}/Jobs?jobId=${jobId}`;
|
||||||
DeleteData(uri);
|
DeleteData(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
function DequeueTask(taskType, connectorName, publicationId){
|
function CancelJob(jobId){
|
||||||
var uri = apiUri + `/Queue/Dequeue?taskType=${taskType}&connectorName=${connectorName}&publicationId=${publicationId}`;
|
var uri = `${apiUri}/Jobs/Cancel?jobId=${jobId}`;
|
||||||
DeleteData(uri);
|
PostData(uri);
|
||||||
}
|
|
||||||
|
|
||||||
async function GetQueue(){
|
|
||||||
var uri = apiUri + "/Queue/List";
|
|
||||||
let json = await GetData(uri);
|
|
||||||
return json;
|
|
||||||
}
|
}
|
@ -20,94 +20,41 @@
|
|||||||
<img id="settingscog" src="media/settings-cogwheel.svg" height="100%" alt="settingscog">
|
<img id="settingscog" src="media/settings-cogwheel.svg" height="100%" alt="settingscog">
|
||||||
</topbar>
|
</topbar>
|
||||||
<viewport>
|
<viewport>
|
||||||
|
<div id="loaderdiv">
|
||||||
|
<blur-background></blur-background>
|
||||||
|
<div id="loader"></div>
|
||||||
|
<p id="loaderText">Check your Settings > API-URI</p>
|
||||||
|
</div>
|
||||||
<content>
|
<content>
|
||||||
<div id="addPublication">
|
<div id="addPublication">
|
||||||
<p>+</p>
|
<p>+</p>
|
||||||
</div>
|
</div>
|
||||||
<publication>
|
<publication onclick="ShowNewMangaSearch()">
|
||||||
<img alt="cover" src="media/cover.jpg">
|
<img alt="cover" src="media/cover.jpg">
|
||||||
<publication-information>
|
<publication-information>
|
||||||
<connector-name class="pill">MangaDex</connector-name>
|
<connector-name class="pill">Sample</connector-name>
|
||||||
<publication-name>Tensei Pandemic</publication-name>
|
<publication-name>Best Manga there is</publication-name>
|
||||||
</publication-information>
|
</publication-information>
|
||||||
</publication>
|
</publication>
|
||||||
</content>
|
</content>
|
||||||
|
|
||||||
<popup id="selectPublicationPopup">
|
<popup id="newMangaPopup">
|
||||||
<blur-background id="blurBackgroundTaskPopup"></blur-background>
|
<blur-background id="blurBackgroundNewMangaPopup" onclick="newMangaPopup.style.display = 'none';"></blur-background>
|
||||||
<popup-window>
|
<div id="newMangaPopupSelector">
|
||||||
<popup-title>Select Publication</popup-title>
|
<select id="newMangaConnector" />
|
||||||
<popup-content>
|
<input type="text" placeholder="Title" id="newMangaTitle" />
|
||||||
<div>
|
<select id="newMangaTranslatedLanguage">
|
||||||
<label for="connectors">Connector</label>
|
<option selected="selected">en</option>
|
||||||
<select id="connectors">
|
<option>it</option>
|
||||||
<option value=""></option>
|
<option>de</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div id="newMangaResult"></div>
|
||||||
<label for="searchPublicationQuery">Search Title</label><input id="searchPublicationQuery" type="text"></addtask-setting>
|
|
||||||
</div>
|
|
||||||
<input type="submit" value="Search" style="font-weight: bolder" onclick="NewSearch();">
|
|
||||||
</popup-content>
|
|
||||||
<div id="taskSelectOutput"></div>
|
|
||||||
</popup-window>
|
|
||||||
</popup>
|
|
||||||
|
|
||||||
<popup id="createMonitorTaskPopup">
|
|
||||||
<blur-background id="blurBackgroundCreateMonitorTaskPopup"></blur-background>
|
|
||||||
<popup-window>
|
|
||||||
<popup-title>Create Task: Monitor Publication</popup-title>
|
|
||||||
<popup-content>
|
|
||||||
<div>
|
|
||||||
<span>Run every</span>
|
|
||||||
<label for="hours"></label><input id="hours" type="number" value="3" min="0" max="23"><span>hours</span>
|
|
||||||
<label for="minutes"></label><input id="minutes" type="number" value="0" min="0" max="59"><span>minutes</span>
|
|
||||||
<input type="submit" value="Create" onclick="AddMonitorTask()">
|
|
||||||
</div>
|
|
||||||
</popup-content>
|
|
||||||
</popup-window>
|
|
||||||
</popup>
|
|
||||||
|
|
||||||
<popup id="createDownloadChaptersTask">
|
|
||||||
<blur-background id="blurBackgroundCreateDownloadChaptersTask"></blur-background>
|
|
||||||
<popup-window>
|
|
||||||
<popup-title>Create Task: Download Chapter(s)</popup-title>
|
|
||||||
<popup-content>
|
|
||||||
<div>
|
|
||||||
<label for="selectedChapters">Chapters:</label><input id="selectedChapters" placeholder="Select"><input type="submit" value="Select" onclick="DownloadChapterTaskClick()">
|
|
||||||
</div>
|
|
||||||
<div id="chapterOutput">
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</popup-content>
|
|
||||||
</popup-window>
|
|
||||||
</popup>
|
|
||||||
|
|
||||||
<popup id="publicationViewerPopup">
|
|
||||||
<blur-background id="blurBackgroundPublicationPopup"></blur-background>
|
|
||||||
<publication-viewer>
|
|
||||||
<img id="pubviewcover" src="media/cover.jpg" alt="cover">
|
|
||||||
<publication-information>
|
|
||||||
<publication-name id="publicationViewerName">Tensei Pandemic</publication-name>
|
|
||||||
<publication-tags id="publicationViewerTags"></publication-tags>
|
|
||||||
<publication-author id="publicationViewerAuthor">Imamura Hinata</publication-author>
|
|
||||||
<publication-description id="publicationViewerDescription">Imamura Hinata is a high school boy with a cute appearance.
|
|
||||||
Since his trauma with the first love, he wanted to be more manly than anybody else. But one day he woke up to something different…
|
|
||||||
The total opposite of his ideal male body!
|
|
||||||
Pandemic love comedy!
|
|
||||||
</publication-description>
|
|
||||||
<publication-interactions>
|
|
||||||
<publication-starttask>Start Task ▶️</publication-starttask>
|
|
||||||
<publication-delete>Delete Task ❌</publication-delete>
|
|
||||||
<publication-add id="createMonitorTaskButton">Monitor ➕</publication-add>
|
|
||||||
<publication-add id="createDownloadChapterTaskButton">Download Chapter ➕</publication-add>
|
|
||||||
</publication-interactions>
|
|
||||||
</publication-information>
|
|
||||||
</publication-viewer>
|
|
||||||
</popup>
|
</popup>
|
||||||
|
|
||||||
<popup id="settingsPopup">
|
<popup id="settingsPopup">
|
||||||
<blur-background id="blurBackgroundSettingsPopup"></blur-background>
|
<blur-background id="blurBackgroundSettingsPopup" onclick="
|
||||||
|
settingsPopup.style.display = 'none';"></blur-background>
|
||||||
<popup-window>
|
<popup-window>
|
||||||
<popup-title>Settings</popup-title>
|
<popup-title>Settings</popup-title>
|
||||||
<popup-content>
|
<popup-content>
|
||||||
@ -145,29 +92,53 @@
|
|||||||
<label for="lunaseaWebhook"></label><input placeholder="device/:id or user/:id" id="lunaseaWebhook" type="text">
|
<label for="lunaseaWebhook"></label><input placeholder="device/:id or user/:id" id="lunaseaWebhook" type="text">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="libraryUpdateTime" style="margin-right: 5px;">Update Time</label><input id="libraryUpdateTime" type="time" value="00:01:00" step="10">
|
<input type="submit" value="Update" onclick="UpdateSettings()">
|
||||||
<input type="submit" value="Update" onclick="UpdateLibrarySettings()">
|
|
||||||
</div>
|
</div>
|
||||||
</popup-content>
|
</popup-content>
|
||||||
</popup-window>
|
</popup-window>
|
||||||
</popup>
|
</popup>
|
||||||
|
|
||||||
|
<popup id="publicationViewerPopup">
|
||||||
|
<blur-background id="blurBackgroundPublicationPopup" onclick="publicationViewerPopup.style.display= 'none';"></blur-background>
|
||||||
|
<publication-viewer>
|
||||||
|
<img id="pubviewcover" src="media/cover.jpg" alt="cover">
|
||||||
|
<publication-information>
|
||||||
|
<publication-name id="publicationViewerName">Best Manga there is</publication-name>
|
||||||
|
<publication-tags id="publicationViewerTags">A Manga</publication-tags>
|
||||||
|
<publication-author id="publicationViewerAuthor">Glax</publication-author>
|
||||||
|
<publication-description id="publicationViewerDescription">
|
||||||
|
An interesting description. The description is very intriguing, yet wholesome.
|
||||||
|
</publication-description>
|
||||||
|
<publication-interactions>
|
||||||
|
<publication-starttask id="startJobButton">Start Job ▶️</publication-starttask>
|
||||||
|
<publication-canceltask id="cancelJobButton">Cancel Job ❌</publication-canceltask>
|
||||||
|
<publication-delete id="deleteJobButton">Delete Job 🗑️</publication-delete>
|
||||||
|
<publication-add id="createMonitorJobButton">Monitor ➕</publication-add>
|
||||||
|
<publication-add id="createDownloadChapterJobButton">Download Chapter 📥</publication-add>
|
||||||
|
</publication-interactions>
|
||||||
|
</publication-information>
|
||||||
|
</publication-viewer>
|
||||||
|
</popup>
|
||||||
|
|
||||||
<popup id="downloadTasksPopup">
|
<popup id="jobStatusView">
|
||||||
<blur-background id="blurBackgroundTasksQueuePopup"></blur-background>
|
<blur-background id="blurBackgroundJobStatus" onclick="jobStatusView.style.display= 'none';"></blur-background>
|
||||||
<popup-window>
|
<popup-window>
|
||||||
<popup-title>Task Progress</popup-title>
|
<div>
|
||||||
<popup-content>
|
<div id="jobStatusRunning" style="border-right: 1px solid gray;"></div>
|
||||||
|
</div>
|
||||||
</popup-content>
|
<div>
|
||||||
|
<div id="jobStatusWaiting" style="border-left: 1px solid gray;"></div>
|
||||||
|
</div>
|
||||||
</popup-window>
|
</popup-window>
|
||||||
</popup>
|
</popup>
|
||||||
</viewport>
|
</viewport>
|
||||||
|
|
||||||
<footer>
|
<footer>
|
||||||
<div onclick="ShowTasksQueue();">
|
<div onclick="ShowJobQueue();">
|
||||||
<img src="media/running.svg" alt="running"><div id="tasksRunningTag">0</div>
|
<img src="media/running.svg" alt="running"><div id="jobsRunningTag">0</div>
|
||||||
</div>
|
</div>
|
||||||
<div onclick="ShowTasksQueue();">
|
<div onclick="ShowJobQueue();">
|
||||||
<img src="media/queue.svg" alt="queue"><div id="tasksQueuedTag">0</div>
|
<img src="media/queue.svg" alt="queue"><div id="jobsQueuedTag">0</div>
|
||||||
</div>
|
</div>
|
||||||
<p id="madeWith">Made with Blåhaj 🦈</p>
|
<p id="madeWith">Made with Blåhaj 🦈</p>
|
||||||
</footer>
|
</footer>
|
||||||
|
@ -1,31 +1,26 @@
|
|||||||
let publications = [];
|
let runningJobs = [];
|
||||||
let tasks = [];
|
let waitingJobs = [];
|
||||||
let toEditId;
|
let notificationConnectorTypes = [];
|
||||||
|
let libraryConnectorTypes = [];
|
||||||
|
let selectedManga;
|
||||||
|
let selectedJob;
|
||||||
|
|
||||||
const searchBox = document.querySelector("#searchbox");
|
const searchBox = document.querySelector("#searchbox");
|
||||||
const searchPublicationQuery = document.querySelector("#searchPublicationQuery");
|
|
||||||
const selectPublication = document.querySelector("#taskSelectOutput");
|
|
||||||
const connectorSelect = document.querySelector("#connectors");
|
|
||||||
const settingsPopup = document.querySelector("#settingsPopup");
|
const settingsPopup = document.querySelector("#settingsPopup");
|
||||||
const settingsCog = document.querySelector("#settingscog");
|
const settingsCog = document.querySelector("#settingscog");
|
||||||
const selectRecurrence = document.querySelector("#selectReccurrence");
|
|
||||||
const tasksContent = document.querySelector("content");
|
const tasksContent = document.querySelector("content");
|
||||||
const selectPublicationPopup = document.querySelector("#selectPublicationPopup");
|
const createMonitorTaskButton = document.querySelector("#createMonitoJobButton");
|
||||||
const createMonitorTaskButton = document.querySelector("#createMonitorTaskButton");
|
const createDownloadChapterTaskButton = document.querySelector("#createDownloadChapterJobButton");
|
||||||
const createDownloadChapterTaskButton = document.querySelector("#createDownloadChapterTaskButton");
|
const startJobButton = document.querySelector("#startJobButton");
|
||||||
const createMonitorTaskPopup = document.querySelector("#createMonitorTaskPopup");
|
const cancelJobButton = document.querySelector("#cancelJobButton");
|
||||||
const createDownloadChaptersTask = document.querySelector("#createDownloadChaptersTask");
|
const deleteJobButton = document.querySelector("#deleteJobButton");
|
||||||
const chapterOutput = document.querySelector("#chapterOutput");
|
const mangaViewerPopup = document.querySelector("#publicationViewerPopup");
|
||||||
const selectedChapters = document.querySelector("#selectedChapters");
|
const mangaViewerWindow = document.querySelector("publication-viewer");
|
||||||
const publicationViewerPopup = document.querySelector("#publicationViewerPopup");
|
const mangaViewerDescription = document.querySelector("#publicationViewerDescription");
|
||||||
const publicationViewerWindow = document.querySelector("publication-viewer");
|
const mangaViewerName = document.querySelector("#publicationViewerName");
|
||||||
const publicationViewerDescription = document.querySelector("#publicationViewerDescription");
|
const mangaViewerTags = document.querySelector("#publicationViewerTags");
|
||||||
const publicationViewerName = document.querySelector("#publicationViewerName");
|
const mangaViewerAuthor = document.querySelector("#publicationViewerAuthor");
|
||||||
const publicationViewerTags = document.querySelector("#publicationViewerTags");
|
const mangaViewCover = document.querySelector("#pubviewcover");
|
||||||
const publicationViewerAuthor = document.querySelector("#publicationViewerAuthor");
|
|
||||||
const pubviewcover = document.querySelector("#pubviewcover");
|
|
||||||
const publicationDelete = document.querySelector("publication-delete");
|
|
||||||
const publicationTaskStart = document.querySelector("publication-starttask");
|
|
||||||
const settingDownloadLocation = document.querySelector("#downloadLocation");
|
const settingDownloadLocation = document.querySelector("#downloadLocation");
|
||||||
const settingKomgaUrl = document.querySelector("#komgaUrl");
|
const settingKomgaUrl = document.querySelector("#komgaUrl");
|
||||||
const settingKomgaUser = document.querySelector("#komgaUsername");
|
const settingKomgaUser = document.querySelector("#komgaUsername");
|
||||||
@ -36,166 +31,55 @@ const settingKavitaPass = document.querySelector("#kavitaPassword");
|
|||||||
const settingGotifyUrl = document.querySelector("#gotifyUrl");
|
const settingGotifyUrl = document.querySelector("#gotifyUrl");
|
||||||
const settingGotifyAppToken = document.querySelector("#gotifyAppToken");
|
const settingGotifyAppToken = document.querySelector("#gotifyAppToken");
|
||||||
const settingLunaseaWebhook = document.querySelector("#lunaseaWebhook");
|
const settingLunaseaWebhook = document.querySelector("#lunaseaWebhook");
|
||||||
const libraryUpdateTime = document.querySelector("#libraryUpdateTime");
|
|
||||||
const settingKomgaConfigured = document.querySelector("#komgaConfigured");
|
const settingKomgaConfigured = document.querySelector("#komgaConfigured");
|
||||||
const settingKavitaConfigured = document.querySelector("#kavitaConfigured");
|
const settingKavitaConfigured = document.querySelector("#kavitaConfigured");
|
||||||
const settingGotifyConfigured = document.querySelector("#gotifyConfigured");
|
const settingGotifyConfigured = document.querySelector("#gotifyConfigured");
|
||||||
const settingLunaseaConfigured = document.querySelector("#lunaseaConfigured");
|
const settingLunaseaConfigured = document.querySelector("#lunaseaConfigured");
|
||||||
const settingApiUri = document.querySelector("#settingApiUri");
|
const settingApiUri = document.querySelector("#settingApiUri");
|
||||||
const tagTasksRunning = document.querySelector("#tasksRunningTag");
|
const newMangaPopup = document.querySelector("#newMangaPopup");
|
||||||
const tagTasksQueued = document.querySelector("#tasksQueuedTag");
|
const newMangaConnector = document.querySelector("#newMangaConnector");
|
||||||
const downloadTasksPopup = document.querySelector("#downloadTasksPopup");
|
const newMangaTitle = document.querySelector("#newMangaTitle");
|
||||||
const downloadTasksOutput = downloadTasksPopup.querySelector("popup-content");
|
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");
|
||||||
|
|
||||||
searchBox.addEventListener("keyup", () => FilterResults());
|
function Setup(){
|
||||||
settingsCog.addEventListener("click", () => OpenSettings());
|
Ping().then((ret) => {
|
||||||
document.querySelector("#blurBackgroundSettingsPopup").addEventListener("click", () => settingsPopup.style.display = "none");
|
loaderdiv.style.display = 'none';
|
||||||
document.querySelector("#blurBackgroundTaskPopup").addEventListener("click", () => selectPublicationPopup.style.display = "none");
|
|
||||||
document.querySelector("#blurBackgroundPublicationPopup").addEventListener("click", () => HidePublicationPopup());
|
GetAvailableNotificationConnectors().then((json) => {
|
||||||
document.querySelector("#blurBackgroundCreateMonitorTaskPopup").addEventListener("click", () => createMonitorTaskPopup.style.display = "none");
|
json.forEach(connector => {
|
||||||
document.querySelector("#blurBackgroundCreateDownloadChaptersTask").addEventListener("click", () => createDownloadChaptersTask.style.display = "none");
|
notificationConnectorTypes[connector.Key] = connector.Value;
|
||||||
document.querySelector("#blurBackgroundTasksQueuePopup").addEventListener("click", () => downloadTasksPopup.style.display = "none");
|
});
|
||||||
selectedChapters.addEventListener("keypress", (event) => {
|
|
||||||
if(event.key === "Enter"){
|
|
||||||
DownloadChapterTaskClick();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
publicationDelete.addEventListener("click", () => DeleteTaskClick());
|
|
||||||
createMonitorTaskButton.addEventListener("click", () => {
|
|
||||||
HidePublicationPopup();
|
|
||||||
createMonitorTaskPopup.style.display = "block";
|
|
||||||
});
|
|
||||||
createDownloadChapterTaskButton.addEventListener("click", () => {
|
|
||||||
HidePublicationPopup();
|
|
||||||
OpenDownloadChapterTaskPopup();
|
|
||||||
});
|
|
||||||
publicationTaskStart.addEventListener("click", () => StartTaskClick());
|
|
||||||
searchPublicationQuery.addEventListener("keypress", (event) => {
|
|
||||||
if(event.key === "Enter"){
|
|
||||||
NewSearch();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
GetAvailableControllers()
|
|
||||||
.then(json => availableConnectors = json)
|
|
||||||
.then(json =>
|
|
||||||
json.forEach(connector => {
|
|
||||||
var option = document.createElement('option');
|
|
||||||
option.value = connector;
|
|
||||||
option.innerText = connector;
|
|
||||||
connectorSelect.appendChild(option);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
function NewSearch(){
|
|
||||||
//Disable inputs
|
|
||||||
connectorSelect.disabled = true;
|
|
||||||
searchPublicationQuery.disabled = true;
|
|
||||||
//Waitcursor
|
|
||||||
document.body.style.cursor = "wait";
|
|
||||||
|
|
||||||
//Empty previous results
|
|
||||||
selectPublication.replaceChildren();
|
|
||||||
GetPublicationFromConnector(connectorSelect.value, searchPublicationQuery.value)
|
|
||||||
.then(json =>
|
|
||||||
json.forEach(publication => {
|
|
||||||
var option = CreatePublication(publication, connectorSelect.value);
|
|
||||||
option.addEventListener("click", (mouseEvent) => {
|
|
||||||
ShowPublicationViewerWindow(publication.internalId, mouseEvent, true);
|
|
||||||
});
|
|
||||||
selectPublication.appendChild(option);
|
|
||||||
}
|
|
||||||
))
|
|
||||||
.then(() => {
|
|
||||||
//Re-enable inputs
|
|
||||||
connectorSelect.disabled = false;
|
|
||||||
searchPublicationQuery.disabled = false;
|
|
||||||
//Cursor
|
|
||||||
document.body.style.cursor = "initial";
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//Returns a new "Publication" Item to display in the tasks section
|
|
||||||
function CreatePublication(publication, connector){
|
|
||||||
var publicationElement = document.createElement('publication');
|
|
||||||
publicationElement.setAttribute("id", publication.internalId);
|
|
||||||
var img = document.createElement('img');
|
|
||||||
img.src = `imageCache/${publication.coverFileNameInCache}`;
|
|
||||||
publicationElement.appendChild(img);
|
|
||||||
var info = document.createElement('publication-information');
|
|
||||||
var connectorName = document.createElement('connector-name');
|
|
||||||
connectorName.innerText = connector;
|
|
||||||
connectorName.className = "pill";
|
|
||||||
info.appendChild(connectorName);
|
|
||||||
var publicationName = document.createElement('publication-name');
|
|
||||||
publicationName.innerText = publication.sortName;
|
|
||||||
info.appendChild(publicationName);
|
|
||||||
publicationElement.appendChild(info);
|
|
||||||
if(publications.filter(pub => pub.internalId === publication.internalId) < 1)
|
|
||||||
publications.push(publication);
|
|
||||||
return publicationElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
function AddMonitorTask(){
|
|
||||||
var hours = document.querySelector("#hours").value;
|
|
||||||
var minutes = document.querySelector("#minutes").value;
|
|
||||||
CreateMonitorTask(connectorSelect.value, toEditId, `${hours}:${minutes}:00`, "en");
|
|
||||||
HidePublicationPopup();
|
|
||||||
createMonitorTaskPopup.style.display = "none";
|
|
||||||
selectPublicationPopup.style.display = "none";
|
|
||||||
}
|
|
||||||
|
|
||||||
function OpenDownloadChapterTaskPopup(){
|
|
||||||
selectedChapters.value = "";
|
|
||||||
chapterOutput.replaceChildren();
|
|
||||||
createDownloadChaptersTask.style.display = "block";
|
|
||||||
GetChapters(toEditId, connectorSelect.value, true, "en").then((json) => {
|
|
||||||
var i = 0;
|
|
||||||
json.forEach(chapter => {
|
|
||||||
var chapterDom = document.createElement("div");
|
|
||||||
var indexDom = document.createElement("span");
|
|
||||||
indexDom.className = "index";
|
|
||||||
indexDom.innerText = i++;
|
|
||||||
chapterDom.appendChild(indexDom);
|
|
||||||
|
|
||||||
var volDom = document.createElement("span");
|
|
||||||
volDom.className = "vol";
|
|
||||||
volDom.innerText = chapter.volumeNumber;
|
|
||||||
chapterDom.appendChild(volDom);
|
|
||||||
|
|
||||||
var chDom = document.createElement("span");
|
|
||||||
chDom.className = "ch";
|
|
||||||
chDom.innerText = chapter.chapterNumber;
|
|
||||||
chapterDom.appendChild(chDom);
|
|
||||||
|
|
||||||
var titleDom = document.createElement("span");
|
|
||||||
titleDom.innerText = chapter.name;
|
|
||||||
chapterDom.appendChild(titleDom);
|
|
||||||
chapterOutput.appendChild(chapterDom);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
function DownloadChapterTaskClick(){
|
GetAvailableLibraryConnectors().then((json) => {
|
||||||
CreateDownloadChaptersTask(connectorSelect.value, toEditId, selectedChapters.value, "en");
|
json.forEach(connector => {
|
||||||
HidePublicationPopup();
|
libraryConnectorTypes[connector.Key] = connector.Value;
|
||||||
createDownloadChaptersTask.style.display = "none";
|
});
|
||||||
selectPublicationPopup.style.display = "none";
|
});
|
||||||
}
|
|
||||||
|
|
||||||
function DeleteTaskClick(){
|
GetAvailableControllers().then((json) => {
|
||||||
taskToDelete = tasks.filter(tTask => tTask.publication.internalId === toEditId)[0];
|
json.forEach(connector => {
|
||||||
DeleteTask("MonitorPublication", taskToDelete.connectorName, toEditId);
|
var option = document.createElement('option');
|
||||||
HidePublicationPopup();
|
option.value = connector;
|
||||||
}
|
option.innerText = connector;
|
||||||
|
newMangaConnector.appendChild(option);
|
||||||
function StartTaskClick(){
|
});
|
||||||
var toEditTask = tasks.filter(task => task.publication.internalId == toEditId)[0];
|
});
|
||||||
StartTask("MonitorPublication", toEditTask.connectorName, toEditId);
|
|
||||||
HidePublicationPopup();
|
UpdateJobs();
|
||||||
|
setInterval(() => {
|
||||||
|
UpdateJobs();
|
||||||
|
}, 1000);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
Setup();
|
||||||
|
|
||||||
function ResetContent(){
|
function ResetContent(){
|
||||||
//Delete everything
|
//Delete everything
|
||||||
@ -207,45 +91,120 @@ function ResetContent(){
|
|||||||
var plus = document.createElement("p");
|
var plus = document.createElement("p");
|
||||||
plus.innerText = "+";
|
plus.innerText = "+";
|
||||||
add.appendChild(plus);
|
add.appendChild(plus);
|
||||||
add.addEventListener("click", () => ShowNewTaskWindow());
|
add.addEventListener("click", () => ShowNewMangaSearch());
|
||||||
tasksContent.appendChild(add);
|
tasksContent.appendChild(add);
|
||||||
}
|
}
|
||||||
function ShowPublicationViewerWindow(publicationId, event, add){
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
newMangaResult.replaceChildren();
|
||||||
|
newMangaConnector.disabled = true;
|
||||||
|
newMangaTitle.disabled = true;
|
||||||
|
newMangaTranslatedLanguage.disabled = true;
|
||||||
|
GetPublicationFromConnector(newMangaConnector.value, newMangaTitle.value).then((json) => {
|
||||||
|
//console.log(json);
|
||||||
|
if(json.length > 0)
|
||||||
|
newMangaResult.style.display = "flex";
|
||||||
|
json.forEach(result => {
|
||||||
|
var mangaElement = CreateManga(result, newMangaConnector.value)
|
||||||
|
newMangaResult.appendChild(mangaElement);
|
||||||
|
mangaElement.addEventListener("click", (event) => {
|
||||||
|
ShowMangaWindow(null, result, event, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
newMangaConnector.disabled = false;
|
||||||
|
newMangaTitle.disabled = false;
|
||||||
|
newMangaTranslatedLanguage.disabled = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//Returns a new "Publication" Item to display in the jobs section
|
||||||
|
function CreateManga(manga, connector){
|
||||||
|
var mangaElement = document.createElement('publication');
|
||||||
|
mangaElement.id = GetValidSelector(manga.internalId);
|
||||||
|
var mangaImage = document.createElement('img');
|
||||||
|
mangaImage.src = GetCoverUrl(manga.internalId);
|
||||||
|
mangaElement.appendChild(mangaImage);
|
||||||
|
var info = document.createElement('publication-information');
|
||||||
|
var connectorName = document.createElement('connector-name');
|
||||||
|
connectorName.innerText = connector;
|
||||||
|
connectorName.className = "pill";
|
||||||
|
info.appendChild(connectorName);
|
||||||
|
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();
|
||||||
|
mangaViewerPopup.style.display = "none";
|
||||||
|
});
|
||||||
|
startJobButton.addEventListener("click", () => {
|
||||||
|
StartJob(selectedJob.id);
|
||||||
|
mangaViewerPopup.style.display = "none";
|
||||||
|
});
|
||||||
|
cancelJobButton.addEventListener("click", () => {
|
||||||
|
CancelJob(selectedJob.id);
|
||||||
|
mangaViewerPopup.style.display = "none";
|
||||||
|
});
|
||||||
|
deleteJobButton.addEventListener("click", () => {
|
||||||
|
RemoveJob(selectedJob.id);
|
||||||
|
UpdateJobs();
|
||||||
|
mangaViewerPopup.style.display = "none";
|
||||||
|
});
|
||||||
|
|
||||||
|
function ShowMangaWindow(job, manga, event, add){
|
||||||
|
selectedManga = manga;
|
||||||
|
selectedJob = job;
|
||||||
//Show popup
|
//Show popup
|
||||||
publicationViewerPopup.style.display = "block";
|
mangaViewerPopup.style.display = "block";
|
||||||
|
|
||||||
//Set position to mouse-position
|
//Set position to mouse-position
|
||||||
if(event.clientY < window.innerHeight - publicationViewerWindow.offsetHeight)
|
if(event.clientY < window.innerHeight - mangaViewerWindow.offsetHeight)
|
||||||
publicationViewerWindow.style.top = `${event.clientY}px`;
|
mangaViewerWindow.style.top = `${event.clientY}px`;
|
||||||
else
|
else
|
||||||
publicationViewerWindow.style.top = `${event.clientY - publicationViewerWindow.offsetHeight}px`;
|
mangaViewerWindow.style.top = `${event.clientY - mangaViewerWindow.offsetHeight}px`;
|
||||||
|
|
||||||
if(event.clientX < window.innerWidth - publicationViewerWindow.offsetWidth)
|
if(event.clientX < window.innerWidth - mangaViewerWindow.offsetWidth)
|
||||||
publicationViewerWindow.style.left = `${event.clientX}px`;
|
mangaViewerWindow.style.left = `${event.clientX}px`;
|
||||||
else
|
else
|
||||||
publicationViewerWindow.style.left = `${event.clientX - publicationViewerWindow.offsetWidth}px`;
|
mangaViewerWindow.style.left = `${event.clientX - mangaViewerWindow.offsetWidth}px`;
|
||||||
|
|
||||||
//Edit information inside the window
|
//Edit information inside the window
|
||||||
var publication = publications.filter(pub => pub.internalId === publicationId)[0];
|
mangaViewerName.innerText = manga.sortName;
|
||||||
publicationViewerName.innerText = publication.sortName;
|
mangaViewerTags.innerText = manga.tags.join(", ");
|
||||||
publicationViewerTags.innerText = publication.tags.join(", ");
|
mangaViewerDescription.innerText = manga.description;
|
||||||
publicationViewerDescription.innerText = publication.description;
|
mangaViewerAuthor.innerText = manga.authors.join(',');
|
||||||
publicationViewerAuthor.innerText = publication.authors.join(',');
|
mangaViewCover.src = GetCoverUrl(manga.internalId);
|
||||||
pubviewcover.src = `imageCache/${publication.coverFileNameInCache}`;
|
toEditId = manga.internalId;
|
||||||
toEditId = publicationId;
|
|
||||||
|
|
||||||
//Check what action should be listed
|
//Check what action should be listed
|
||||||
if(add){
|
if(add){
|
||||||
createMonitorTaskButton.style.display = "initial";
|
createMonitorJobButton.style.display = "initial";
|
||||||
createDownloadChapterTaskButton.style.display = "initial";
|
createDownloadChapterJobButton.style.display = "none";
|
||||||
publicationDelete.style.display = "none";
|
cancelJobButton.style.display = "none";
|
||||||
publicationTaskStart.style.display = "none";
|
startJobButton.style.display = "none";
|
||||||
|
deleteJobButton.style.display = "none";
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
createMonitorTaskButton.style.display = "none";
|
createMonitorJobButton.style.display = "none";
|
||||||
createDownloadChapterTaskButton.style.display = "none";
|
createDownloadChapterJobButton.style.display = "none";
|
||||||
publicationDelete.style.display = "initial";
|
cancelJobButton.style.display = "initial";
|
||||||
publicationTaskStart.style.display = "initial";
|
startJobButton.style.display = "initial";
|
||||||
|
deleteJobButton.style.display = "initial";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,108 +212,8 @@ function HidePublicationPopup(){
|
|||||||
publicationViewerPopup.style.display = "none";
|
publicationViewerPopup.style.display = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
function ShowNewTaskWindow(){
|
searchBox.addEventListener("keyup", () => FilterResults());
|
||||||
selectPublication.replaceChildren();
|
//Filter shown jobs
|
||||||
searchPublicationQuery.value = "";
|
|
||||||
selectPublicationPopup.style.display = "flex";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fadeIn = [
|
|
||||||
{ opacity: "0" },
|
|
||||||
{ opacity: "1" }
|
|
||||||
];
|
|
||||||
|
|
||||||
const fadeInTiming = {
|
|
||||||
duration: 50,
|
|
||||||
iterations: 1,
|
|
||||||
fill: "forwards"
|
|
||||||
}
|
|
||||||
|
|
||||||
function OpenSettings(){
|
|
||||||
GetSettingsClick();
|
|
||||||
settingsPopup.style.display = "flex";
|
|
||||||
}
|
|
||||||
|
|
||||||
function GetSettingsClick(){
|
|
||||||
settingApiUri.value = "";
|
|
||||||
settingKomgaUrl.value = "";
|
|
||||||
settingKomgaUser.value = "";
|
|
||||||
settingKomgaPass.value = "";
|
|
||||||
settingKomgaConfigured.innerText = "❌";
|
|
||||||
settingKavitaUrl.value = "";
|
|
||||||
settingKavitaUser.value = "";
|
|
||||||
settingKavitaPass.value = "";
|
|
||||||
settingKavitaConfigured.innerText = "❌";
|
|
||||||
settingGotifyUrl.value = "";
|
|
||||||
settingGotifyAppToken.value = "";
|
|
||||||
settingGotifyConfigured.innerText = "❌";
|
|
||||||
settingLunaseaWebhook.value = "";
|
|
||||||
settingLunaseaConfigured.innerText = "❌";
|
|
||||||
|
|
||||||
settingApiUri.placeholder = apiUri;
|
|
||||||
|
|
||||||
GetSettings().then(json => {
|
|
||||||
settingDownloadLocation.innerText = json.downloadLocation;
|
|
||||||
json.libraryManagers.forEach(lm => {
|
|
||||||
if(lm.libraryType == 0){
|
|
||||||
settingKomgaUrl.placeholder = lm.baseUrl;
|
|
||||||
settingKomgaUser.placeholder = "User";
|
|
||||||
settingKomgaPass.placeholder = "***";
|
|
||||||
settingKomgaConfigured.innerText = "✅";
|
|
||||||
} else if(lm.libraryType == 1){
|
|
||||||
settingKavitaUrl.placeholder = lm.baseUrl;
|
|
||||||
settingKavitaUser.placeholder = "User";
|
|
||||||
settingKavitaPass.placeholder = "***";
|
|
||||||
settingKavitaConfigured.innerText = "✅";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
json.notificationManagers.forEach(nm => {
|
|
||||||
if(nm.notificationManagerType == 0){
|
|
||||||
settingGotifyConfigured.innerText = "✅";
|
|
||||||
} else if(nm.notificationManagerType == 1){
|
|
||||||
settingLunaseaConfigured.innerText = "✅";
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
GetKomgaTask().then(json => {
|
|
||||||
if(json.length > 0)
|
|
||||||
libraryUpdateTime.value = json[0].reoccurrence;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function UpdateLibrarySettings(){
|
|
||||||
if(settingKomgaUrl.value != "" && settingKomgaUser.value != "" && settingKomgaPass.value != ""){
|
|
||||||
var auth = utf8_to_b64(`${settingKomgaUser.value}:${settingKomgaPass.value}`);
|
|
||||||
console.log(auth);
|
|
||||||
UpdateKomga(settingKomgaUrl.value, auth);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(settingApiUri.value != ""){
|
|
||||||
apiUri = settingApiUri.value;
|
|
||||||
document.cookie = `apiUri=${apiUri};`;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => GetSettingsClick(), 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
function utf8_to_b64( str ) {
|
|
||||||
return window.btoa(unescape(encodeURIComponent( str )));
|
|
||||||
}
|
|
||||||
|
|
||||||
function FilterResults(){
|
function FilterResults(){
|
||||||
if(searchBox.value.length > 0){
|
if(searchBox.value.length > 0){
|
||||||
tasksContent.childNodes.forEach(publication => {
|
tasksContent.childNodes.forEach(publication => {
|
||||||
@ -377,147 +236,249 @@ function FilterResults(){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ShowTasksQueue(){
|
settingsCog.addEventListener("click", () => {
|
||||||
|
OpenSettings();
|
||||||
|
settingsPopup.style.display = "flex";
|
||||||
|
});
|
||||||
|
|
||||||
downloadTasksOutput.replaceChildren();
|
settingKomgaUrl.addEventListener("keypress", (event) => { { if(event.key === "Enter") UpdateSettings(); } });
|
||||||
GetRunningTasks()
|
settingKomgaUser.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
||||||
.then(json => {
|
settingKomgaPass.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
||||||
tagTasksRunning.innerText = json.length;
|
settingKavitaUrl.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
||||||
json.forEach(task => {
|
settingKavitaUser.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
||||||
if(task.task == 2 || task.task == 4) {
|
settingKavitaPass.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
||||||
downloadTasksOutput.appendChild(CreateProgressChild(task));
|
settingGotifyUrl.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
||||||
document.querySelector(`#progress${GetValidSelector(task.taskId)}`).value = task.progress;
|
settingGotifyAppToken.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
||||||
var finishedHours = task.executionApproximatelyRemaining.split(':')[0];
|
settingLunaseaWebhook.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
||||||
var finishedMinutes = task.executionApproximatelyRemaining.split(':')[1];
|
settingApiUri.addEventListener("keypress", (event) => { if(event.key === "Enter") UpdateSettings(); });
|
||||||
var finishedSeconds = task.executionApproximatelyRemaining.split(':')[2].split('.')[0];
|
|
||||||
document.querySelector(`#progressStr${GetValidSelector(task.taskId)}`).innerText = `${finishedHours}:${finishedMinutes}:${finishedSeconds}`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
GetQueue()
|
function OpenSettings(){
|
||||||
.then(json => {
|
settingGotifyConfigured.innerText = "❌";
|
||||||
tagTasksQueued.innerText = json.length;
|
settingLunaseaConfigured.innerText = "❌";
|
||||||
json.forEach(task => {
|
settingKavitaConfigured.innerText = "❌";
|
||||||
downloadTasksOutput.appendChild(CreateProgressChild(task));
|
settingKomgaConfigured.innerText = "❌";
|
||||||
});
|
settingKomgaUrl.value = "";
|
||||||
});
|
settingKomgaUser.value = "";
|
||||||
downloadTasksPopup.style.display = "flex";
|
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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function CreateProgressChild(task){
|
function UpdateSettings(){
|
||||||
var child = document.createElement("div");
|
if(settingApiUri.value != ""){
|
||||||
var img = document.createElement('img');
|
apiUri = settingApiUri.value;
|
||||||
img.src = `imageCache/${task.publication.coverFileNameInCache}`;
|
setCookie("apiUri", apiUri);
|
||||||
child.appendChild(img);
|
Setup();
|
||||||
|
}
|
||||||
var name = document.createElement("span");
|
|
||||||
name.innerText = task.publication.sortName;
|
if(settingKomgaUrl.value != "" &&
|
||||||
name.className = "pubTitle";
|
settingKomgaUser.value != "" &&
|
||||||
child.appendChild(name);
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
function utf8_to_b64(str) {
|
||||||
|
return window.btoa(unescape(encodeURIComponent( str )));
|
||||||
|
}
|
||||||
|
|
||||||
var progress = document.createElement("progress");
|
function UpdateJobs(){
|
||||||
progress.id = `progress${GetValidSelector(task.taskId)}`;
|
GetMonitorJobs().then((json) => {
|
||||||
child.appendChild(progress);
|
ResetContent();
|
||||||
|
//console.log(json);
|
||||||
|
json.forEach(job => {
|
||||||
|
var mangaView = CreateManga(job.manga, job.mangaConnector.name);
|
||||||
|
mangaView.addEventListener("click", (event) => {
|
||||||
|
ShowMangaWindow(job, job.manga, event, false);
|
||||||
|
});
|
||||||
|
tasksContent.appendChild(mangaView);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var progressStr = document.createElement("span");
|
GetWaitingJobs().then((json) => {
|
||||||
progressStr.innerText = " \t∞";
|
jobsQueuedTag.innerText = json.length;
|
||||||
progressStr.className = "progressStr";
|
|
||||||
progressStr.id = `progressStr${GetValidSelector(task.taskId)}`;
|
|
||||||
child.appendChild(progressStr);
|
|
||||||
|
|
||||||
if(task.chapter != undefined){
|
var nowWaitingJobs = [];
|
||||||
var chapterNumber = document.createElement("span");
|
|
||||||
chapterNumber.className = "chapterNumber";
|
json.forEach(job => {
|
||||||
chapterNumber.innerText = `Vol.${task.chapter.volumeNumber} Ch.${task.chapter.chapterNumber}`;
|
if(!waitingJobs.includes(GetValidSelector(job.id))){
|
||||||
child.appendChild(chapterNumber);
|
var jobDom = createJob(job);
|
||||||
|
jobStatusWaiting.appendChild(jobDom);
|
||||||
var chapterName = document.createElement("span");
|
}
|
||||||
chapterName.className = "chapterName";
|
nowWaitingJobs.push(GetValidSelector(job.id));
|
||||||
chapterName.innerText = task.chapter.name;
|
});
|
||||||
child.appendChild(chapterName);
|
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);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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%";
|
||||||
return child;
|
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}`;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Resets the tasks shown
|
|
||||||
ResetContent();
|
|
||||||
downloadTasksOutput.replaceChildren();
|
|
||||||
//Get Tasks and show them
|
|
||||||
GetDownloadTasks()
|
|
||||||
.then(json => json.forEach(task => {
|
|
||||||
var publication = CreatePublication(task.publication, task.connectorName);
|
|
||||||
publication.addEventListener("click", (event) => ShowPublicationViewerWindow(task.publication.internalId, event, false));
|
|
||||||
tasksContent.appendChild(publication);
|
|
||||||
tasks.push(task);
|
|
||||||
}));
|
|
||||||
|
|
||||||
GetRunningTasks()
|
|
||||||
.then(json => {
|
|
||||||
tagTasksRunning.innerText = json.length;
|
|
||||||
json.forEach(task => {
|
|
||||||
downloadTasksOutput.appendChild(CreateProgressChild(task));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
GetQueue()
|
|
||||||
.then(json => {
|
|
||||||
tagTasksQueued.innerText = json.length;
|
|
||||||
json.forEach(task => {
|
|
||||||
downloadTasksOutput.appendChild(CreateProgressChild(task));
|
|
||||||
});
|
|
||||||
})
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
//Tasks from API
|
|
||||||
var cTasks = [];
|
|
||||||
GetDownloadTasks()
|
|
||||||
.then(json => json.forEach(task => cTasks.push(task)))
|
|
||||||
.then(() => {
|
|
||||||
//Only update view if tasks-amount has changed
|
|
||||||
if(tasks.length != cTasks.length) {
|
|
||||||
//Resets the tasks shown
|
|
||||||
ResetContent();
|
|
||||||
//Add all currenttasks to view
|
|
||||||
cTasks.forEach(task => {
|
|
||||||
var publication = CreatePublication(task.publication, task.connectorName);
|
|
||||||
publication.addEventListener("click", (event) => ShowPublicationViewerWindow(task.publication.internalId, event, false));
|
|
||||||
tasksContent.appendChild(publication);
|
|
||||||
})
|
|
||||||
|
|
||||||
tasks = cTasks;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
GetRunningTasks()
|
|
||||||
.then(json => {
|
|
||||||
tagTasksRunning.innerText = json.length;
|
|
||||||
});
|
|
||||||
|
|
||||||
GetQueue()
|
|
||||||
.then(json => {
|
|
||||||
tagTasksQueued.innerText = json.length;
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
setInterval(() => {
|
|
||||||
GetRunningTasks().then((json) => {
|
|
||||||
json.forEach(task => {
|
|
||||||
if(task.task == 2 || task.task == 4){
|
|
||||||
document.querySelector(`#progress${GetValidSelector(task.taskId)}`).value = task.progress;
|
|
||||||
var finishedHours = task.executionApproximatelyRemaining.split(':')[0];
|
|
||||||
var finishedMinutes = task.executionApproximatelyRemaining.split(':')[1];
|
|
||||||
var finishedSeconds = task.executionApproximatelyRemaining.split(':')[2].split('.')[0];
|
|
||||||
document.querySelector(`#progressStr${GetValidSelector(task.taskId)}`).innerText = `${finishedHours}:${finishedMinutes}:${finishedSeconds}`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},500);
|
|
||||||
|
|
||||||
function GetValidSelector(str){
|
function GetValidSelector(str){
|
||||||
var clean = [...str.matchAll(/[a-zA-Z0-9]*-*_*/g)];
|
var clean = [...str.matchAll(/[a-zA-Z0-9]*-*_*/g)];
|
||||||
return clean.join('');
|
return clean.join('');
|
||||||
|
@ -148,7 +148,7 @@ content {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#settingsPopup{
|
#settingsPopup{
|
||||||
z-index: 10;
|
z-index: 300;
|
||||||
}
|
}
|
||||||
|
|
||||||
#settingsPopup popup-content{
|
#settingsPopup popup-content{
|
||||||
@ -205,6 +205,7 @@ publication{
|
|||||||
margin: 10px 10px;
|
margin: 10px 10px;
|
||||||
padding: 15px 20px;
|
padding: 15px 20px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
publication::after{
|
publication::after{
|
||||||
@ -305,138 +306,57 @@ popup popup-window popup-content input, select {
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#selectPublicationPopup publication {
|
#newMangaPopup > div {
|
||||||
width: 150px;
|
z-index: 3;
|
||||||
height: 250px;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
#createTaskPopup {
|
#newMangaPopup > #newMangaPopupSelector {
|
||||||
z-index: 7;
|
width: 600px;
|
||||||
|
height: 40px;
|
||||||
|
margin: 80px auto 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#createTaskPopup input {
|
#newMangaPopup > div > #newMangaConnector, #newMangaTitle, #newMangaTranslatedLanguage {
|
||||||
height: 30px;
|
margin: 0;
|
||||||
width: 200px;
|
display: inline-block;
|
||||||
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#createMonitorTaskPopup, #createDownloadChaptersTask {
|
#newMangaPopup #newMangaConnector {
|
||||||
z-index: 9;
|
width: 100px;
|
||||||
|
padding: 0 0 0 5px;
|
||||||
|
border-radius: 5px 0 0 5px;
|
||||||
|
border: 0;
|
||||||
|
border-right: 1px solid darkgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
#createMonitorTaskPopup input[type="number"] {
|
#newMangaPopup #newMangaTitle{
|
||||||
width: 40px;
|
width: 445px;
|
||||||
|
padding: 0 5px 0 5px;
|
||||||
|
border: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#createDownloadChaptersTask popup-content {
|
#newMangaPopup #newMangaTranslatedLanguage {
|
||||||
flex-direction: column;
|
width: 45px;
|
||||||
align-items: start;
|
border-radius: 0 5px 5px 0;
|
||||||
|
border: 0;
|
||||||
|
border-left: 1px solid darkgray;
|
||||||
|
margin-left: -5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#createDownloadChaptersTask popup-content > * {
|
#newMangaResult {
|
||||||
margin: 3px 0;
|
display: none;
|
||||||
}
|
flex-direction: row;
|
||||||
|
justify-content: flex-start;
|
||||||
#createDownloadChaptersTask #chapterOutput {
|
margin: 5px auto 0;
|
||||||
max-height: 50vh;
|
border-radius: 5px;
|
||||||
overflow-y: scroll;
|
padding: 5px;
|
||||||
}
|
width: min-content;
|
||||||
|
max-width: 98%;
|
||||||
#createDownloadChaptersTask #chapterOutput .index{
|
max-height: 400px;
|
||||||
display: inline-block;
|
overflow-x: scroll;
|
||||||
width: 25px;
|
overflow-y: hidden;
|
||||||
}
|
|
||||||
|
|
||||||
#createDownloadChaptersTask #chapterOutput .index::after{
|
|
||||||
content: ':';
|
|
||||||
}
|
|
||||||
|
|
||||||
#createDownloadChaptersTask #chapterOutput .vol::before{
|
|
||||||
content: 'Vol.';
|
|
||||||
}
|
|
||||||
|
|
||||||
#createDownloadChaptersTask #chapterOutput .vol{
|
|
||||||
display: inline-block;
|
|
||||||
width: 45px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#createDownloadChaptersTask #chapterOutput .ch::before{
|
|
||||||
content: 'Ch.';
|
|
||||||
}
|
|
||||||
|
|
||||||
#createDownloadChaptersTask #chapterOutput .ch {
|
|
||||||
display: inline-block;
|
|
||||||
width: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#downloadTasksPopup popup-window {
|
|
||||||
left: 0;
|
|
||||||
top: 80px;
|
|
||||||
margin: 0 0 0 10px;
|
|
||||||
height: calc(100vh - 140px);
|
|
||||||
width: 400px;
|
|
||||||
max-width: 95vw;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
#downloadTasksPopup popup-content {
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: start;
|
|
||||||
margin: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#downloadTasksPopup popup-content > div {
|
|
||||||
display: block;
|
|
||||||
height: 80px;
|
|
||||||
position: relative;
|
|
||||||
margin: 5px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#downloadTasksPopup popup-content > div > img {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
height: 100%;
|
|
||||||
width: 60px;
|
|
||||||
left: 0;
|
|
||||||
top: 0;
|
|
||||||
object-fit: cover;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#downloadTasksPopup popup-content > div > span {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
width: max-content;
|
|
||||||
}
|
|
||||||
|
|
||||||
#downloadTasksPopup popup-content > div > .pubTitle {
|
|
||||||
left: 70px;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#downloadTasksPopup popup-content > div > .chapterName {
|
|
||||||
left: 70px;
|
|
||||||
top: 28pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
#downloadTasksPopup popup-content > div > .chapterNumber {
|
|
||||||
left: 70px;
|
|
||||||
top: 14pt;
|
|
||||||
}
|
|
||||||
|
|
||||||
#downloadTasksPopup popup-content > div > progress {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
left: 150px;
|
|
||||||
bottom: 0;
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#downloadTasksPopup popup-content > div > .progressStr {
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
left: 70px;
|
|
||||||
bottom: 0;
|
|
||||||
width: 70px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blur-background {
|
blur-background {
|
||||||
@ -444,18 +364,10 @@ blur-background {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
background-color: black;
|
background: rgba(245, 169, 184, 0.58);
|
||||||
opacity: 0.5;
|
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.1);
|
||||||
}
|
backdrop-filter: blur(4.5px);
|
||||||
|
-webkit-backdrop-filter: blur(4.5px);
|
||||||
#taskSelectOutput{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: start;
|
|
||||||
align-content: start;
|
|
||||||
max-height: 70vh;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#publicationViewerPopup{
|
#publicationViewerPopup{
|
||||||
@ -464,7 +376,7 @@ blur-background {
|
|||||||
|
|
||||||
publication-viewer{
|
publication-viewer{
|
||||||
display: block;
|
display: block;
|
||||||
width: 450px;
|
width: 460px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 200px;
|
top: 200px;
|
||||||
left: 400px;
|
left: 400px;
|
||||||
@ -559,6 +471,10 @@ publication-viewer publication-information publication-interactions publication-
|
|||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publication-view publication-information publication-interactions publication-canceltask {
|
||||||
|
color: yellow;
|
||||||
|
}
|
||||||
|
|
||||||
publication-viewer publication-information publication-interactions publication-add {
|
publication-viewer publication-information publication-interactions publication-add {
|
||||||
color: limegreen;
|
color: limegreen;
|
||||||
}
|
}
|
||||||
@ -600,4 +516,123 @@ footer-tag-popup::before{
|
|||||||
left: 0;
|
left: 0;
|
||||||
bottom: -17px;
|
bottom: -17px;
|
||||||
border-radius: 0 0 0 5px;
|
border-radius: 0 0 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loaderdiv {
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loader {
|
||||||
|
border: 16px solid transparent;
|
||||||
|
border-top: 16px solid var(--secondary-color);
|
||||||
|
border-bottom: 16px solid var(--primary-color);
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 120px;
|
||||||
|
height: 120px;
|
||||||
|
animation: spin 2s linear infinite;
|
||||||
|
position: absolute;
|
||||||
|
left: calc(50% - 60px);
|
||||||
|
top: calc(50% - 120px);
|
||||||
|
z-index: 201;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loaderText {
|
||||||
|
position: relative;
|
||||||
|
margin: 0 auto;
|
||||||
|
top: calc(50% + 80px);
|
||||||
|
z-index: 201;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--second-background-color);
|
||||||
|
font-size: 20pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% { transform: rotate(0deg); }
|
||||||
|
100% { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
#jobStatusView {
|
||||||
|
z-index: 50;
|
||||||
|
}
|
||||||
|
|
||||||
|
#jobStatusView > popup-window {
|
||||||
|
top: 80px;
|
||||||
|
width: 50%;
|
||||||
|
max-height: calc(100% - 140px);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
#jobStatusView > popup-window > div {
|
||||||
|
overflow-y: scroll;
|
||||||
|
overflow-x: hidden;
|
||||||
|
width: 50%;
|
||||||
|
margin: 0;
|
||||||
|
max-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#jobStatusView > popup-window > div > div {
|
||||||
|
overflow-x: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
width: 100%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jobWrapper {
|
||||||
|
width: 90%;
|
||||||
|
margin: 2px 5%;
|
||||||
|
height: 100px;
|
||||||
|
position: relative;
|
||||||
|
flex-shrink: 0;
|
||||||
|
background-color: rgba(187,187,187,0.4);
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jobWrapper > .jobImage {
|
||||||
|
height: 90%;
|
||||||
|
width: 20%;
|
||||||
|
left: 5px;
|
||||||
|
object-fit: contain;
|
||||||
|
position: absolute;
|
||||||
|
top: 5%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jobWrapper > .jobTitle {
|
||||||
|
position: absolute;
|
||||||
|
left: calc(20% + 10px);
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jobWrapper > .jobProgressBar {
|
||||||
|
position: absolute;
|
||||||
|
left: calc(20% + 10px);
|
||||||
|
bottom: calc(12pt + 10px);
|
||||||
|
width: calc(80% - 20px);
|
||||||
|
height: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jobWrapper > .jobProgressSpan {
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
bottom: calc(12pt + 20px);
|
||||||
|
width: 60%;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jobWrapper > .jobCancel {
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
bottom: 5px;
|
||||||
|
font-size: 12pt;
|
||||||
|
color: var(--secondary-color);
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
version: '3'
|
version: '3'
|
||||||
services:
|
services:
|
||||||
tranga-api:
|
tranga-api:
|
||||||
image: glax/tranga-api:latest
|
image: glax/tranga-api:cuttingedge
|
||||||
container_name: tranga-api
|
container_name: tranga-api
|
||||||
volumes:
|
volumes:
|
||||||
- ./tranga:/usr/share/Tranga-API #1 when replacing ./tranga replace #2 with same value
|
- ./tranga:/usr/share/Tranga-API #1 when replacing ./tranga replace #2 with same value
|
||||||
@ -10,7 +10,7 @@ services:
|
|||||||
- "6531:6531"
|
- "6531:6531"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
tranga-website:
|
tranga-website:
|
||||||
image: glax/tranga-website:latest
|
image: glax/tranga-website:cuttingedge
|
||||||
container_name: tranga-website
|
container_name: tranga-website
|
||||||
volumes:
|
volumes:
|
||||||
- ./tranga/imageCache:/usr/share/nginx/html/imageCache:ro #2 when replacing Point to same value as #1/imageCache
|
- ./tranga/imageCache:/usr/share/nginx/html/imageCache:ro #2 when replacing Point to same value as #1/imageCache
|
||||||
|
Loading…
x
Reference in New Issue
Block a user