mirror of
https://github.com/PhoenixTwoFive/karaoqueue.git
synced 2025-05-20 19:41:49 +02:00
Use bootstrap-table for fancy ajax tables.
This commit is contained in:
parent
41b2aa2ed1
commit
3ed8146b6f
34
.vscode/launch.json
vendored
34
.vscode/launch.json
vendored
@ -6,6 +6,7 @@
|
|||||||
"configurations": [
|
"configurations": [
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{"name":"Python: Flask","type":"python","request":"launch","module":"flask","env":{"FLASK_APP":"app/main.py","FLASK_ENV":"development","FLASK_DEBUG":"1"},"args":["run","--no-debugger","--no-reload"],"jinja":true},
|
{"name":"Python: Flask","type":"python","request":"launch","module":"flask","env":{"FLASK_APP":"app/main.py","FLASK_ENV":"development","FLASK_DEBUG":"1"},"args":["run","--no-debugger","--no-reload"],"jinja":true},
|
||||||
{"name":"Python: Flask (with reload)","type":"python","request":"launch","module":"flask","env":{"FLASK_APP":"app/main.py","FLASK_ENV":"development","FLASK_DEBUG":"1"},"args":["run","--no-debugger"],"jinja":true},
|
{"name":"Python: Flask (with reload)","type":"python","request":"launch","module":"flask","env":{"FLASK_APP":"app/main.py","FLASK_ENV":"development","FLASK_DEBUG":"1"},"args":["run","--no-debugger"],"jinja":true},
|
||||||
{
|
{
|
||||||
@ -25,6 +26,24 @@
|
|||||||
],
|
],
|
||||||
"jinja": true
|
"jinja": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "Python: Flask (externally reachable)",
|
||||||
|
"type": "python",
|
||||||
|
"request": "launch",
|
||||||
|
"module": "flask",
|
||||||
|
"env": {
|
||||||
|
"FLASK_APP": "app/main.py",
|
||||||
|
"FLASK_ENV": "development",
|
||||||
|
"FLASK_DEBUG": "1"
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
"run",
|
||||||
|
"--no-debugger",
|
||||||
|
"--no-reload",
|
||||||
|
"--host='0.0.0.0'"
|
||||||
|
],
|
||||||
|
"jinja": true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "Python: Current File (Integrated Terminal)",
|
"name": "Python: Current File (Integrated Terminal)",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
@ -65,21 +84,6 @@
|
|||||||
],
|
],
|
||||||
"django": true
|
"django": true
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name": "Python: Flask",
|
|
||||||
"type": "python",
|
|
||||||
"request": "launch",
|
|
||||||
"module": "flask",
|
|
||||||
"env": {
|
|
||||||
"FLASK_APP": "app.py"
|
|
||||||
},
|
|
||||||
"args": [
|
|
||||||
"run",
|
|
||||||
"--no-debugger",
|
|
||||||
"--no-reload"
|
|
||||||
],
|
|
||||||
"jinja": true
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "Python: Current File (External Terminal)",
|
"name": "Python: Current File (External Terminal)",
|
||||||
"type": "python",
|
"type": "python",
|
||||||
|
8
app/data_adapters.py
Normal file
8
app/data_adapters.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
def dict_from_row(row):
|
||||||
|
return dict(zip(row.keys(), row))
|
||||||
|
|
||||||
|
def dict_from_rows(rows):
|
||||||
|
outlist=[]
|
||||||
|
for row in rows:
|
||||||
|
outlist.append(dict_from_row(row))
|
||||||
|
return outlist
|
@ -74,6 +74,7 @@ def create_done_song_view():
|
|||||||
|
|
||||||
def get_list():
|
def get_list():
|
||||||
conn = open_db()
|
conn = open_db()
|
||||||
|
conn.row_factory = sqlite3.Row
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
cur.execute("SELECT * FROM Liste")
|
cur.execute("SELECT * FROM Liste")
|
||||||
return cur.fetchall()
|
return cur.fetchall()
|
||||||
@ -141,6 +142,20 @@ def delete_entry(id):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def delete_entries(ids):
|
||||||
|
idlist = []
|
||||||
|
for x in ids:
|
||||||
|
idlist.append( (x,) )
|
||||||
|
try:
|
||||||
|
conn = open_db()
|
||||||
|
cur = conn.cursor()
|
||||||
|
cur.executemany("DELETE FROM entries WHERE id=?", idlist)
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
return cur.rowcount
|
||||||
|
except sqlite3.Error as error:
|
||||||
|
return -1
|
||||||
|
|
||||||
def delete_all_entries():
|
def delete_all_entries():
|
||||||
conn = open_db()
|
conn = open_db()
|
||||||
cur = conn.cursor()
|
cur = conn.cursor()
|
||||||
|
24
app/main.py
24
app/main.py
@ -1,6 +1,7 @@
|
|||||||
from flask import Flask, render_template, Response, abort, request, redirect
|
from flask import Flask, render_template, Response, abort, request, redirect
|
||||||
import helpers
|
import app.helpers as helpers
|
||||||
import database
|
import app.database as database
|
||||||
|
import app.data_adapters as data_adapters
|
||||||
import os, errno
|
import os, errno
|
||||||
import json
|
import json
|
||||||
from flask_basicauth import BasicAuth
|
from flask_basicauth import BasicAuth
|
||||||
@ -29,6 +30,11 @@ def enqueue():
|
|||||||
def songlist():
|
def songlist():
|
||||||
return render_template('songlist.html', list=database.get_song_list(), auth=basic_auth.authenticate())
|
return render_template('songlist.html', list=database.get_song_list(), auth=basic_auth.authenticate())
|
||||||
|
|
||||||
|
@app.route("/api/queue")
|
||||||
|
def queue_json():
|
||||||
|
list = data_adapters.dict_from_rows(database.get_list())
|
||||||
|
return Response(json.dumps(list, ensure_ascii=False).encode('utf-8'), mimetype='text/json')
|
||||||
|
|
||||||
@app.route("/plays")
|
@app.route("/plays")
|
||||||
@basic_auth.required
|
@basic_auth.required
|
||||||
def played_list():
|
def played_list():
|
||||||
@ -69,6 +75,20 @@ def delete_entry(entry_id):
|
|||||||
return Response('{"status": "FAIL"}', mimetype='text/json')
|
return Response('{"status": "FAIL"}', mimetype='text/json')
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/api/entries/delete", methods=['POST'])
|
||||||
|
@basic_auth.required
|
||||||
|
def delete_entries():
|
||||||
|
if not request.json:
|
||||||
|
print(request.data)
|
||||||
|
abort(400)
|
||||||
|
return
|
||||||
|
updates = database.delete_entries(request.json)
|
||||||
|
if updates >= 0:
|
||||||
|
return Response('{"status": "OK", "updates": '+str(updates)+'}', mimetype='text/json')
|
||||||
|
else:
|
||||||
|
return Response('{"status": "FAIL"}', mimetype='text/json', status=400)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/api/entries/mark_sung/<entry_id>")
|
@app.route("/api/entries/mark_sung/<entry_id>")
|
||||||
@basic_auth.required
|
@basic_auth.required
|
||||||
def mark_sung(entry_id):
|
def mark_sung(entry_id):
|
||||||
|
@ -26,15 +26,11 @@ main {
|
|||||||
|
|
||||||
.topbutton {
|
.topbutton {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-right: auto;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.topbutton {
|
.topbutton {
|
||||||
width: auto;
|
width: auto;
|
||||||
margin-right: 1rem;
|
|
||||||
margin-bottom: auto;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@
|
|||||||
|
|
||||||
<title>{% block title %}{% endblock %} - KaraoQueue</title>
|
<title>{% block title %}{% endblock %} - KaraoQueue</title>
|
||||||
|
|
||||||
|
<!-- Bootstrap-Tables -->
|
||||||
|
<link rel="stylesheet" href="https://unpkg.com/bootstrap-table@1.15.3/dist/bootstrap-table.min.css">
|
||||||
|
|
||||||
<!-- Bootstrap core CSS -->
|
<!-- Bootstrap core CSS -->
|
||||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"
|
||||||
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
|
||||||
@ -18,9 +21,10 @@
|
|||||||
<!-- Custom styles for this template -->
|
<!-- Custom styles for this template -->
|
||||||
<link href="static/css/style.css" rel="stylesheet">
|
<link href="static/css/style.css" rel="stylesheet">
|
||||||
|
|
||||||
<!-- Fontawesome Icons-->
|
<!-- Fontawesome Icons -->
|
||||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css"
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.2/css/all.css"
|
||||||
integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay" crossorigin="anonymous">
|
integrity="sha384-oS3vJWv+0UjzBfQzYUhtDYW+Pj2yciDJxpsK1OYPAYjqT085Qq/1cq5FLXAZQ7Ay" crossorigin="anonymous">
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@ -88,6 +92,7 @@
|
|||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"
|
||||||
integrity="sha256-4F7e4JsAJyLUdpP7Q8Sah866jCOhv72zU5E8lIRER4w=" crossorigin="anonymous">
|
integrity="sha256-4F7e4JsAJyLUdpP7Q8Sah866jCOhv72zU5E8lIRER4w=" crossorigin="anonymous">
|
||||||
</script>
|
</script>
|
||||||
|
<script src="https://unpkg.com/bootstrap-table@1.15.3/dist/bootstrap-table.min.js"></script>
|
||||||
{% block extrajs %}{% endblock %}
|
{% block extrajs %}{% endblock %}
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
@ -3,28 +3,19 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% block title %}Warteliste{% endblock %}
|
{% block title %}Warteliste{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<a role="button" class="btn btn-primary btn-lg btn-block" href="/list">Eintragen</a>
|
<a role="button" class="btn btn-primary btn-lg btn-block mb-2" href="/list">Eintragen</a>
|
||||||
<table class="table">
|
<table class="table"
|
||||||
|
data-toggle="table"
|
||||||
|
data-url="/api/queue"
|
||||||
|
data-pagination="true"
|
||||||
|
data-classes="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">Name</th>
|
<th scope="col" data-field="Name">Name</th>
|
||||||
<th scope="col">Song</th>
|
<th scope="col" data-field="Title">Song</th>
|
||||||
<th scope="col">Künstler</th>
|
<th scope="col" data-field="Artist">Künstler</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
{% for entry in list: %}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{{ entry[0] }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ entry[1] }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ entry[2] }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
</table>
|
||||||
<a name="end"></a>
|
<a name="end"></a>
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -4,53 +4,37 @@
|
|||||||
{% block title %}Warteliste-Admin{% endblock %}
|
{% block title %}Warteliste-Admin{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div id="toolbar">
|
||||||
<div class="card" style="width: 100%">
|
<button type="button" class="topbutton btn btn-danger" onclick="confirmDeleteSelectedEntries()"><i
|
||||||
<div class="card-body">
|
class="fas fa-trash mr-2"></i>Gewählte Einträge löschen</button>
|
||||||
<button type="button" class="topbutton btn btn-danger"
|
<button type="button" class="topbutton btn btn-danger" onclick="confirmUpdateSongDatabase()"><i
|
||||||
onclick="confirmDeleteAllEntries()"><i class="fas fa-trash mr-2"></i>Alle Einträge löschen</button>
|
class="fas fa-file-import mr-2"></i>Song-Datenbank
|
||||||
<button type="button" class="topbutton btn btn-danger"
|
aktualisieren</button>
|
||||||
onclick="confirmUpdateSongDatabase()"><i class="fas fa-file-import mr-2"></i>Song-Datenbank
|
|
||||||
aktualisieren</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<table class="table"
|
||||||
<table class="table">
|
id="entrytable"
|
||||||
<thead>
|
data-toggle="table"
|
||||||
<tr>
|
data-search="true"
|
||||||
<th scope="col">Name</th>
|
data-show-columns="true"
|
||||||
<th scope="col">Song</th>
|
data-show-toggle="true"
|
||||||
<th scope="col">Künstler</th>
|
data-multiple-select-row="true"
|
||||||
<th scope="col">Aktionen</th>
|
data-click-to-select="true"
|
||||||
</tr>
|
data-toolbar="#toolbar"
|
||||||
</thead>
|
data-pagination="true"
|
||||||
{% for entry in list: %}
|
data-show-extended-pagination="true"
|
||||||
|
data-classes="table table-hover"
|
||||||
|
data-url="/api/queue">
|
||||||
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<th data-field="state" data-checkbox="true"></th>
|
||||||
{{ entry[0] }}
|
<th scope="col" data-field="Name">Name</th>
|
||||||
</td>
|
<th scope="col" data-field="Title">Song</th>
|
||||||
<td>
|
<th scope="col" data-field="Artist">Künstler</th>
|
||||||
{{ entry[1] }}
|
<th scope="col" data-formatter="TableActions">Aktionen</th>
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{{ entry[2] }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<button type='button' class='btn btn-success'
|
|
||||||
data-toggle="tooltip" data-placement="top" title="Als gesungen markieren"
|
|
||||||
onclick='markEntryAsSung({{ entry[3] }})'><i
|
|
||||||
class="fas fa-check"></i></button>
|
|
||||||
<button type='button' class='btn btn-danger'
|
|
||||||
data-toggle="tooltip" data-placement="top" title="Eintrag löschen"
|
|
||||||
onclick='confirmDeleteEntry("{{ entry[0] }}",{{ entry[3] }})'><i
|
|
||||||
class="fas fa-trash"></i></button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
<a name="end"></a>
|
<a name="end"></a>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block extrajs %}
|
{% block extrajs %}
|
||||||
@ -65,9 +49,9 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
function confirmDeleteAllEntries() {
|
function confirmDeleteSelectedEntries() {
|
||||||
bootbox.confirm({
|
bootbox.confirm({
|
||||||
message: "Wirklich alle Eintragungen löschen?",
|
message: "Wirklich gewählte Eintragungen löschen?",
|
||||||
buttons: {
|
buttons: {
|
||||||
confirm: {
|
confirm: {
|
||||||
label: 'Ja',
|
label: 'Ja',
|
||||||
@ -80,7 +64,7 @@
|
|||||||
},
|
},
|
||||||
callback: function(result){
|
callback: function(result){
|
||||||
if (result) {
|
if (result) {
|
||||||
deleteAllEntries()
|
DeleteSelectedEntries(getIdSelections())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -118,7 +102,7 @@
|
|||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
async: false
|
async: false
|
||||||
});
|
});
|
||||||
location.reload();
|
$("#entrytable").bootstrapTable('refresh')
|
||||||
}
|
}
|
||||||
function markEntryAsSung(entry_id) {
|
function markEntryAsSung(entry_id) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -128,17 +112,24 @@
|
|||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
async: false
|
async: false
|
||||||
});
|
});
|
||||||
location.reload();
|
$("#entrytable").bootstrapTable('refresh')
|
||||||
}
|
}
|
||||||
function deleteAllEntries() {
|
function DeleteSelectedEntries(ids) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: 'GET',
|
type: 'POST',
|
||||||
url: '/api/entries/delete_all',
|
url: '/api/entries/delete',
|
||||||
|
data: JSON.stringify(ids), // or JSON.stringify ({name: 'jonas'}),
|
||||||
|
error: function() {
|
||||||
|
bootbox.alert({
|
||||||
|
message: "Fehler beim Löschen der Eintragungen.",
|
||||||
|
})
|
||||||
|
},
|
||||||
|
success: function() {
|
||||||
|
$("#entrytable").bootstrapTable('refresh')
|
||||||
|
},
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
dataType: 'json',
|
dataType: 'json'
|
||||||
async: false
|
|
||||||
});
|
});
|
||||||
location.reload();
|
|
||||||
}
|
}
|
||||||
function updateSongDatabase(wait_dialog) {
|
function updateSongDatabase(wait_dialog) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
@ -150,10 +141,18 @@
|
|||||||
wait_dialog.modal('hide')
|
wait_dialog.modal('hide')
|
||||||
bootbox.alert({
|
bootbox.alert({
|
||||||
message: data["status"],
|
message: data["status"],
|
||||||
callback: function() {location.reload()}
|
callback: function() {$("#entrytable").bootstrapTable('refresh')}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
function TableActions (value, row, index) {
|
||||||
|
return "<button type='button' class='btn btn-success' data-toggle=\"tooltip\" data-placement=\"top\" title=\"Als gesungen markieren\" onclick='markEntryAsSung("+row.ID+")'><i class=\"fas fa-check\"></i></button> <button type='button' class='btn btn-danger' data-toggle=\"tooltip\" data-placement=\"top\" title=\"Eintrag löschen\" onclick='confirmDeleteEntry(\""+row.Name+"\","+row.ID+")'><i class=\"fas fa-trash\"></i></button>";
|
||||||
|
}
|
||||||
|
function getIdSelections() {
|
||||||
|
return $.map($("#entrytable").bootstrapTable('getSelections'), function (row) {
|
||||||
|
return row.ID
|
||||||
|
})
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -1,15 +1,23 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% block title %}Abspielliste{% endblock %}
|
{% block title %}Abspielliste{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="card admincontrols" style="width: 100%">
|
<div id="toolbar">
|
||||||
<div class="card-body">
|
<button type="button" class="topbutton btn btn-danger" onclick="confirmDeleteAllEntries()"><i
|
||||||
<button type="button" class="topbutton btn btn-danger" onclick="confirmDeleteAllEntries()"><i
|
class="fas fa-trash mr-2"></i>Abspielliste löschen</button>
|
||||||
class="fas fa-trash mr-2"></i>Abspielliste löschen</button>
|
<button type="button" class="topbutton btn btn-primary" onclick="exportPDF()"><i
|
||||||
<button type="button" class="topbutton btn btn-primary" onclick="exportPDF()"><i class="fas fa-file-pdf mr-2"></i>Als PDF herunterladen</button>
|
class="fas fa-file-pdf mr-2"></i>Als PDF herunterladen</button>
|
||||||
<button type="button" class="topbutton btn btn-secondary" onclick="printPDF()"><i class="fas fa-print mr-2"></i>Drucken</button>
|
<button type="button" class="topbutton btn btn-secondary" onclick="printPDF()"><i
|
||||||
</div>
|
class="fas fa-print mr-2"></i>Drucken</button>
|
||||||
</div>
|
</div>
|
||||||
<table class="table" id="table">
|
<table class="table"
|
||||||
|
id="table"
|
||||||
|
data-toggle="table"
|
||||||
|
data-search="true"
|
||||||
|
data-show-columns="true"
|
||||||
|
data-toolbar="#toolbar"
|
||||||
|
data-pagination="true"
|
||||||
|
data-classes="table table-bordered table-striped"
|
||||||
|
data-show-extended-pagination="true">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col">Song</th>
|
<th scope="col">Song</th>
|
||||||
@ -67,7 +75,8 @@
|
|||||||
function exportPDF() {
|
function exportPDF() {
|
||||||
var doc = new jsPDF();
|
var doc = new jsPDF();
|
||||||
doc.autoTable({
|
doc.autoTable({
|
||||||
html: '#table',
|
head: [["Song","Wiedergaben"]],
|
||||||
|
body: createTableArray(),
|
||||||
theme: 'grid'
|
theme: 'grid'
|
||||||
});
|
});
|
||||||
doc.save('Abspielliste.pdf');
|
doc.save('Abspielliste.pdf');
|
||||||
@ -76,11 +85,18 @@
|
|||||||
function printPDF() {
|
function printPDF() {
|
||||||
var doc = new jsPDF();
|
var doc = new jsPDF();
|
||||||
doc.autoTable({
|
doc.autoTable({
|
||||||
html: '#table',
|
head: [["Song","Wiedergaben"]],
|
||||||
|
body: createTableArray(),
|
||||||
theme: 'grid'
|
theme: 'grid'
|
||||||
});
|
});
|
||||||
doc.autoPrint();
|
doc.autoPrint();
|
||||||
doc.output('dataurlnewwindow');
|
doc.output('dataurlnewwindow');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createTableArray() {
|
||||||
|
var data = $("#table").bootstrapTable('getData')
|
||||||
|
out = data.map(x => [x["0"],x["1"]])
|
||||||
|
return out;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
@ -4,16 +4,6 @@
|
|||||||
<input class="form-control" id="filter" type="text" placeholder="Suchen...">
|
<input class="form-control" id="filter" type="text" placeholder="Suchen...">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tbody id="songtable">
|
<tbody id="songtable">
|
||||||
<!--{% for entry in (): %}
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{{ entry[0] }}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<button type="button" class="btn btn-primary"><i class="material-icons">queue_music</i></button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}-->
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<div class="modal fade" id="enqueueModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
<div class="modal fade" id="enqueueModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user