table with search and sortable columns
This commit is contained in:
parent
77f6137d1e
commit
bd20839335
60
src/main.py
60
src/main.py
@ -1,7 +1,16 @@
|
|||||||
import psycopg2
|
import psycopg2
|
||||||
|
|
||||||
from flask import Flask, render_template
|
from flask import Flask, render_template
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import config
|
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
if os.environ.get('PRODUCTION'):
|
||||||
|
import config
|
||||||
|
else:
|
||||||
|
import config
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
app.debug = True
|
app.debug = True
|
||||||
@ -11,6 +20,13 @@ sql_statement = 'SELECT "id","title","alias","shortid","viewcount","lastchangeAt
|
|||||||
|
|
||||||
@app.route("/")
|
@app.route("/")
|
||||||
def main():
|
def main():
|
||||||
|
if os.environ.get('PRODUCTION'):
|
||||||
|
return production()
|
||||||
|
else:
|
||||||
|
return testing()
|
||||||
|
|
||||||
|
|
||||||
|
def production():
|
||||||
DB_HOST = os.environ.get('DB_HOST')
|
DB_HOST = os.environ.get('DB_HOST')
|
||||||
DB_NAME = os.environ.get('POSTGRES_DB')
|
DB_NAME = os.environ.get('POSTGRES_DB')
|
||||||
DB_USER = os.environ.get('POSTGRES_USER')
|
DB_USER = os.environ.get('POSTGRES_USER')
|
||||||
@ -34,5 +50,47 @@ def main():
|
|||||||
return render_template('index.html')
|
return render_template('index.html')
|
||||||
|
|
||||||
|
|
||||||
|
def testing():
|
||||||
|
notes_arr = []
|
||||||
|
notes_arr.append(
|
||||||
|
{
|
||||||
|
'id': "SJBWsApiX",
|
||||||
|
'title': "None",
|
||||||
|
'alias': "35c3",
|
||||||
|
'shortid': "SJBWsApiX",
|
||||||
|
'viewcount': "0",
|
||||||
|
'lastchangeAt': datetime(2013, 10, 31, 18, 23, 29, 227),
|
||||||
|
'permission': "freely",
|
||||||
|
'content': "xxx"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
x = {
|
||||||
|
'id': "SJBWsApiX",
|
||||||
|
'title': "Protokoll für die Fachschaftssitzung vom 6. Februar 2019",
|
||||||
|
'alias': "35c3",
|
||||||
|
'shortid': "SJBWsApiX",
|
||||||
|
'viewcount': "0",
|
||||||
|
'lastchangeAt': datetime(2013, 10, 31, 18, 23, 29, 227),
|
||||||
|
'permission': "freely"
|
||||||
|
}
|
||||||
|
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
notes_arr.append(x)
|
||||||
|
|
||||||
|
return render_template('index.html', notes=notes_arr, host=config.CODI_URL)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
app.run(host='0.0.0.0', port=5000)
|
app.run(host='0.0.0.0', port=5000)
|
||||||
|
|||||||
@ -1,47 +1,16 @@
|
|||||||
/*.extra-content {*/
|
table.dataTable thead .sorting:after,
|
||||||
/*display: none;*/
|
table.dataTable thead .sorting:before,
|
||||||
/*text-decoration: none !important;*/
|
table.dataTable thead .sorting_asc:after,
|
||||||
/*color: #0b2e13;*/
|
table.dataTable thead .sorting_asc:before,
|
||||||
/*}*/
|
table.dataTable thead .sorting_asc_disabled:after,
|
||||||
|
table.dataTable thead .sorting_asc_disabled:before,
|
||||||
/*.sortable a {*/
|
table.dataTable thead .sorting_desc:after,
|
||||||
/*display: inline-block;*/
|
table.dataTable thead .sorting_desc:before,
|
||||||
/*}*/
|
table.dataTable thead .sorting_desc_disabled:after,
|
||||||
|
table.dataTable thead .sorting_desc_disabled:before {
|
||||||
/*.sortable a:hover .extra-content {*/
|
bottom: .5em;
|
||||||
/*display: block;*/
|
|
||||||
/*text-decoration: none !important;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.sortable a:hover .extra-content p {*/
|
|
||||||
/*display: block;*/
|
|
||||||
/*text-decoration: none !important;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
.fancy-tooltip {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.fancy-tooltip .tooltiptext {
|
.dataTables_length, .dataTables_info, .dataTables_paginate {
|
||||||
visibility: hidden;
|
visibility: hidden
|
||||||
width: 300px;
|
|
||||||
background-color: #555;
|
|
||||||
color: #fff;
|
|
||||||
text-align: center;
|
|
||||||
border-radius: 6px;
|
|
||||||
padding: 5px 0;
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
bottom: -170%;
|
|
||||||
left: 50%;
|
|
||||||
margin-left: -60px;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.3s;
|
|
||||||
line-height: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fancy-tooltip:hover .tooltiptext {
|
|
||||||
visibility: visible;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
}
|
||||||
@ -1,61 +1,5 @@
|
|||||||
function updateParent(notesArr) {
|
$(document).ready(function () {
|
||||||
let parent = document.getElementById('sortable-wrapper');
|
$('#example').DataTable({
|
||||||
parent.innerHTML = '';
|
"lengthMenu": [[-1],["All"]]
|
||||||
for (let elem of notesArr) {
|
});
|
||||||
parent.appendChild(elem);
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertToArray() {
|
|
||||||
var notes = document.getElementsByClassName("sortable");
|
|
||||||
var notesArr = [];
|
|
||||||
for (const node of notes) {
|
|
||||||
notesArr.push(node);
|
|
||||||
}
|
|
||||||
return notesArr;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortByTitle() {
|
|
||||||
var sort_by_title = function (a, b) {
|
|
||||||
let x = a.getElementsByClassName('note-title')[0];
|
|
||||||
let y = b.getElementsByClassName('note-title')[0];
|
|
||||||
return x.innerHTML.toLowerCase().localeCompare(y.innerHTML.toLowerCase());
|
|
||||||
};
|
|
||||||
|
|
||||||
var notesArr = convertToArray();
|
|
||||||
notesArr.sort(sort_by_title);
|
|
||||||
updateParent(notesArr);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortByDate() {
|
|
||||||
console.log('Sort Date');
|
|
||||||
var sort_by_date = function (a, b) {
|
|
||||||
a = a.getElementsByClassName('note-date')[0];
|
|
||||||
b = b.getElementsByClassName('note-date')[0];
|
|
||||||
if (a && b) {
|
|
||||||
a = a.innerHTML.split(' ');
|
|
||||||
let a_date = a[0].split('.');
|
|
||||||
let a_time = a[1].split(':');
|
|
||||||
b = b.innerHTML.split('\ ');
|
|
||||||
let b_date = b[0].split('.');
|
|
||||||
let b_time = b[1].split(':');
|
|
||||||
let x = new Date(a_date[2], a_date[1], a_date[0], a_time[0], a_time[1]).getTime();
|
|
||||||
let y = new Date(b_date[2], b_date[1], b_date[0], b_time[0], b_time[1]).getTime();
|
|
||||||
if (x === y) {
|
|
||||||
return 0;
|
|
||||||
} else if (x > y) {
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return x.innerHTML.toLowerCase().localeCompare(y.innerHTML.toLowerCase());
|
|
||||||
};
|
|
||||||
|
|
||||||
var notesArr = convertToArray();
|
|
||||||
notesArr.sort(sort_by_date);
|
|
||||||
updateParent(notesArr);
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,45 +1,53 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>CodiMD Notes</title>
|
<title>CodiMD Notes</title>
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.12/js/jquery.dataTables.min.js"></script>
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.13/js/dataTables.bootstrap4.min.js"></script>
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='libs/bootstrap.min.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='libs/bootstrap.min.css') }}">
|
||||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
|
||||||
<script src="{{ url_for('static', filename='js/sort.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/sort.js') }}"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-light">
|
|
||||||
<nav class="navbar navbar-light bg-light">
|
<body>
|
||||||
<a class="navbar-brand" href="#">
|
<nav class="navbar navbar-light bg-light">
|
||||||
CodiMD Notes
|
<a class="navbar-brand" href="#">
|
||||||
</a>
|
<h1>CodiMD Notes</h1>
|
||||||
</nav>
|
</a>
|
||||||
<div class="container-fluid">
|
</nav>
|
||||||
<div class="row mb-2">
|
|
||||||
<div class="col">
|
<div class="container">
|
||||||
<button class="btn btn-success" onclick="sortByTitle()">Sort By Title</button>
|
<!-- <table id="dtBasicExample" class="table table-striped table-bordered table-sm" cellspacing="0" width="100%"> -->
|
||||||
<button class="btn btn-success" onclick="sortByDate()">Sort By Date</button>
|
<table id="example" class="table table-striped table-inverse table-bordered table-hover" cellspacing="0" width="100%">
|
||||||
</div>
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>id</th>
|
||||||
|
<th>title</th>
|
||||||
|
<th>alias</th>
|
||||||
|
<th>last change at</th>
|
||||||
|
<th>permission</th>
|
||||||
|
<th>content</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for note in notes %}
|
||||||
|
<tr>
|
||||||
|
<td scope="row"><a class="" href="{{host}}/{{note['shortid']}}">{{note['shortid']}}</a></td>
|
||||||
|
<td>{{note['title']}}</td>
|
||||||
|
<td>{{note['alias']}}</td>
|
||||||
|
<td><span class="note-date">{{note['lastchangeAt'].strftime('%d.%m.%Y %H:%M')}}</span></td>
|
||||||
|
<td>{{note['permission']}}</td>
|
||||||
|
<td>{%if note['content']%}💬{%else%}❌{%endif%}</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<!-- </div> -->
|
||||||
</div>
|
</div>
|
||||||
<div id="sortable-wrapper" class="row">
|
|
||||||
{% for note in notes %}
|
|
||||||
<div class="fancy-tooltip sortable col-12">
|
|
||||||
<a class="" href="{{host}}/{{note['shortid']}}">
|
|
||||||
<h5 class="note-title">{{note['title']}}</h5>
|
|
||||||
<div class="tooltiptext">
|
|
||||||
{% if note['lastchangeAt'] %}
|
|
||||||
<h6 class="mb-2">LastChanged: <span class="note-date">{{note['lastchangeAt'].strftime('%d.%m.%Y %H:%M')}}</span>
|
|
||||||
</h6>
|
|
||||||
{% endif %}
|
|
||||||
<p>ViewCount: {{note['viewcount']}}</p>
|
|
||||||
<p>Permission: {{note['permission']}}</p>
|
|
||||||
<p>Alias: {{note['alias']}}</p>
|
|
||||||
<p>Short ID: {{note['shortid']}}</p>
|
|
||||||
<p>Content: {%if note['content']%}Ja{%else%}Nein{%endif%}</p>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user