feat: basic table display
This commit is contained in:
@@ -55,7 +55,7 @@ TEMPLATES = [
|
|||||||
{
|
{
|
||||||
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
"BACKEND": "django.template.backends.django.DjangoTemplates",
|
||||||
"DIRS": [
|
"DIRS": [
|
||||||
'epub2go_web/templates/'
|
"epub2go_web/templates/"
|
||||||
],
|
],
|
||||||
"APP_DIRS": True,
|
"APP_DIRS": True,
|
||||||
"OPTIONS": {
|
"OPTIONS": {
|
||||||
@@ -118,6 +118,9 @@ USE_TZ = True
|
|||||||
# https://docs.djangoproject.com/en/5.1/howto/static-files/
|
# https://docs.djangoproject.com/en/5.1/howto/static-files/
|
||||||
|
|
||||||
STATIC_URL = "static/"
|
STATIC_URL = "static/"
|
||||||
|
STATICFILES_DIRS = [
|
||||||
|
BASE_DIR / "epub2go_web/static",
|
||||||
|
]
|
||||||
|
|
||||||
# Default primary key field type
|
# Default primary key field type
|
||||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
|
# https://docs.djangoproject.com/en/5.1/ref/settings/#default-auto-field
|
||||||
|
|||||||
1
src/epub2go_web/static/bookmark.svg
Normal file
1
src/epub2go_web/static/bookmark.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M0 48C0 21.5 21.5 0 48 0l0 48 0 393.4 130.1-92.9c8.3-6 19.6-6 27.9 0L336 441.4 336 48 48 48 48 0 336 0c26.5 0 48 21.5 48 48l0 440c0 9-5 17.2-13 21.3s-17.6 3.4-24.9-1.8L192 397.5 37.9 507.5c-7.3 5.2-16.9 5.9-24.9 1.8S0 497 0 488L0 48z"/></svg>
|
||||||
|
After Width: | Height: | Size: 465 B |
1
src/epub2go_web/static/download.svg
Normal file
1
src/epub2go_web/static/download.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M64 0C28.7 0 0 28.7 0 64L0 448c0 35.3 28.7 64 64 64l256 0c35.3 0 64-28.7 64-64l0-288-128 0c-17.7 0-32-14.3-32-32L224 0 64 0zM256 0l0 128 128 0L256 0zM216 232l0 102.1 31-31c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-72 72c-9.4 9.4-24.6 9.4-33.9 0l-72-72c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l31 31L168 232c0-13.3 10.7-24 24-24s24 10.7 24 24z"/></svg>
|
||||||
|
After Width: | Height: | Size: 573 B |
1
src/epub2go_web/static/github.svg
Normal file
1
src/epub2go_web/static/github.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
1
src/epub2go_web/static/open-link.svg
Normal file
1
src/epub2go_web/static/open-link.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l82.7 0L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3l0 82.7c0 17.7 14.3 32 32 32s32-14.3 32-32l0-160c0-17.7-14.3-32-32-32L320 0zM80 32C35.8 32 0 67.8 0 112L0 432c0 44.2 35.8 80 80 80l320 0c44.2 0 80-35.8 80-80l0-112c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 112c0 8.8-7.2 16-16 16L80 448c-8.8 0-16-7.2-16-16l0-320c0-8.8 7.2-16 16-16l112 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L80 32z"/></svg>
|
||||||
|
After Width: | Height: | Size: 673 B |
28
src/epub2go_web/static/script.js
Normal file
28
src/epub2go_web/static/script.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// needs to be included at bottom to get document references
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const searchInput = document.getElementById('searchInput');
|
||||||
|
const table = document.getElementById('table');
|
||||||
|
const table_r = Array.from(table.getElementsByTagName('tr'));
|
||||||
|
|
||||||
|
// allow search from url parameter
|
||||||
|
let searchParam = params.get('s');
|
||||||
|
if (searchParam){
|
||||||
|
searchInput.value = searchParam;
|
||||||
|
search(searchParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitSearch(event){
|
||||||
|
event.preventDefault();
|
||||||
|
search();
|
||||||
|
}
|
||||||
|
function search(searchStr = searchInput.value){
|
||||||
|
function showMatch(tr){
|
||||||
|
// match search with list
|
||||||
|
let searchSuccess = Array.from(tr.getElementsByClassName('table-data')).map(e => e.textContent)
|
||||||
|
.join(' ')
|
||||||
|
.indexOf(searchStr) > -1;
|
||||||
|
if (searchSuccess) tr.style.display = "";
|
||||||
|
else tr.style.display = "none";
|
||||||
|
}
|
||||||
|
table_r.map(showMatch, table_r);
|
||||||
|
}
|
||||||
11
src/epub2go_web/static/styles.css
Normal file
11
src/epub2go_web/static/styles.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
tr:nth-child(even){
|
||||||
|
background-color: #EEEEEE;
|
||||||
|
}
|
||||||
|
.table-icon{
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
.header-icon{
|
||||||
|
vertical-align: middle;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
@@ -1,11 +1,20 @@
|
|||||||
|
{% load static %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>{{ title }}</title>
|
<title>{{ title }}</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="{% static 'styles.css' %}">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
|
<div>
|
||||||
<h1>{{ title }}</h1>
|
<h1>{{ title }}</h1>
|
||||||
|
<a href="javascript:void(window.open('./?t='+encodeURIComponent(window.location.toString())))" title="Add this to your bookmarks"> <!--TODO fix domain part as variable-->
|
||||||
|
<img src="{% static 'bookmark.svg' %}" alt="Bookmarklet" class="header-icon">
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/eneller/epub2go.py">
|
||||||
|
<img src="{% static 'github.svg' %}" alt="GitHub" class="header-icon">
|
||||||
|
</a></div>
|
||||||
<search>
|
<search>
|
||||||
<form onsubmit="submitSearch(event)">
|
<form onsubmit="submitSearch(event)">
|
||||||
<input type="su" id="searchInput" placeholder="Search">
|
<input type="su" id="searchInput" placeholder="Search">
|
||||||
@@ -13,51 +22,35 @@
|
|||||||
</search>
|
</search>
|
||||||
</header>
|
</header>
|
||||||
<table id="table">
|
<table id="table">
|
||||||
{% for item in items %}
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>Title</th>
|
||||||
|
<th>Author</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for item in books %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href= {{ item.url }} target="_blank" rel="noopener noreferrer">
|
||||||
|
<img src="{% static 'open-link.svg' %}" alt="Open Link" class="table-icon">
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
<td class="table-data">
|
<td class="table-data">
|
||||||
<a href= {{ item.url }}>
|
<a href= {{ item.url }}>
|
||||||
{{ item.title }}
|
{{ item.title }}
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td>Download</td>
|
<td>
|
||||||
|
<a> {{ item.author }}</a>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<footer>
|
<footer>
|
||||||
<a href="javascript:void(window.open('./?t='+encodeURIComponent(window.location.toString())))">Bookmarklet</a> <!--TODO fix domain part as variable-->
|
|
||||||
<a href="https://github.com/eneller/epub2go.py">GitHub</a>
|
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
<script>
|
<script src="{% static 'script.js' %}"></script>
|
||||||
// get document references
|
|
||||||
const params = new URLSearchParams(window.location.search);
|
|
||||||
const searchInput = document.getElementById('searchInput');
|
|
||||||
const table = document.getElementById('table');
|
|
||||||
const table_r = Array.from(table.getElementsByTagName('tr'));
|
|
||||||
|
|
||||||
// allow search from url parameter
|
|
||||||
let searchParam = params.get('s');
|
|
||||||
if (searchParam){
|
|
||||||
searchInput.value = searchParam;
|
|
||||||
search(searchParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
function submitSearch(event){
|
|
||||||
event.preventDefault();
|
|
||||||
search();
|
|
||||||
}
|
|
||||||
function search(searchStr = searchInput.value){
|
|
||||||
function showMatch(tr){
|
|
||||||
// match search with list
|
|
||||||
let searchSuccess = Array.from(tr.getElementsByClassName('table-data')).map(e => e.textContent)
|
|
||||||
.join(' ')
|
|
||||||
.indexOf(searchStr) > -1;
|
|
||||||
if (searchSuccess) tr.style.display = "";
|
|
||||||
else tr.style.display = "none";
|
|
||||||
}
|
|
||||||
table_r.map(showMatch, table_r);
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
|
||||||
@@ -19,10 +19,12 @@ from django.contrib import admin
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django.shortcuts import render, redirect
|
from django.shortcuts import render, redirect
|
||||||
|
from epub2go.convert import get_all_books, GBConvert, Book
|
||||||
|
|
||||||
def root(request:HttpRequest):
|
def root(request:HttpRequest):
|
||||||
title = 'epub2go'
|
title = 'epub2go'
|
||||||
targetParam = request.GET.get('t', None)
|
targetParam = request.GET.get('t', None)
|
||||||
|
books = get_all_books()
|
||||||
if targetParam is not None:
|
if targetParam is not None:
|
||||||
getEpub(targetParam)
|
getEpub(targetParam)
|
||||||
return render(request, 'index.html', locals())
|
return render(request, 'index.html', locals())
|
||||||
@@ -33,6 +35,7 @@ urlpatterns = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
def getEpub(param):
|
def getEpub(param):
|
||||||
|
print(param)
|
||||||
# TODO validate / sanitize input
|
# TODO validate / sanitize input
|
||||||
# TODO check for existing file and age
|
# TODO check for existing file and age
|
||||||
# TODO download
|
# TODO download
|
||||||
|
|||||||
Reference in New Issue
Block a user