API + Styling changes
This commit is contained in:
parent
47ae9a846f
commit
195febfe17
|
@ -24,7 +24,7 @@ def getBooksData(userid, year = None):
|
|||
engine = create_engine('mysql+mysqldb://' + ras.settings.DATABASES['default']['USER'] + ':' + ras.settings.DATABASES['default']['PASSWORD'] + '@' + ras.settings.DATABASES['default']['HOST'] + ':3306/' + ras.settings.DATABASES['default']['NAME'])
|
||||
|
||||
if year:
|
||||
sql = 'SELECT * FROM api_books WHERE userid = ' + userid + ' AND year = ' + str(year) + ' ORDER BY readed'
|
||||
sql = "SELECT * FROM api_books WHERE userid = " + userid + " AND YEAR(readed) IN ('" + str(year) + "') ORDER BY readed"
|
||||
else:
|
||||
sql = 'SELECT * FROM api_books WHERE userid = ' + userid + ' ORDER BY readed'
|
||||
|
||||
|
|
|
@ -5,6 +5,23 @@ from rest_framework.response import Response
|
|||
from django.http import JsonResponse
|
||||
from .functions import isAuthorized, getBooksData, filterData
|
||||
|
||||
@api_view(['GET'])
|
||||
def getBooksByYear(request):
|
||||
if(request.headers.get('Authorization')):
|
||||
isLoggedIn = isAuthorized(request.headers.get('Authorization'));
|
||||
|
||||
if(isLoggedIn):
|
||||
if request.META.get('HTTP_YEAR'):
|
||||
df = getBooksData(request.headers.get('userid'), request.META.get('HTTP_YEAR'))
|
||||
data = df.to_dict(orient='records')
|
||||
return Response(data)
|
||||
else:
|
||||
return JsonResponse({'error': 'No year header included'}, safe=False)
|
||||
else:
|
||||
return JsonResponse({'error': 'No user detected'}, safe=False)
|
||||
else:
|
||||
return JsonResponse({'error': 'Unauthorized'}, safe=False)
|
||||
|
||||
# ----------------------
|
||||
# Get all reading years
|
||||
# ----------------------
|
||||
|
|
|
@ -9,7 +9,7 @@ from .modules.predictions import *
|
|||
|
||||
urlpatterns = [
|
||||
path('books/all', getAllBooks),
|
||||
# path('books', getBooksByYear),
|
||||
path('books', getBooksByYear),
|
||||
path('books/years', getYears),
|
||||
path('books/stats', getStats),
|
||||
path('books/insert', addBook),
|
||||
|
|
|
@ -16,18 +16,14 @@ export const initDataTable = () => {
|
|||
table.destroy();
|
||||
setTimeout(() => {
|
||||
table = new DataTable('#DataTable', {
|
||||
columnDefs: [
|
||||
{ width: '20%', targets: "_all" }
|
||||
],
|
||||
fixedColumns: true,
|
||||
autoWidth: true,
|
||||
language: {
|
||||
url: 'https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Dutch.json',
|
||||
search: "",
|
||||
searchPlaceholder: "Zoeken"
|
||||
},
|
||||
dom: 'rt<"bottom"pl><"clear">',
|
||||
order: [],
|
||||
"autoWidth": true
|
||||
order: []
|
||||
});
|
||||
}, 300)
|
||||
}
|
|
@ -22,6 +22,21 @@ export const loginUser = (username, password, formData) => {
|
|||
})
|
||||
}
|
||||
|
||||
export const getBooksByYear = (year) => {
|
||||
return fetch('/api/books', {
|
||||
"method": "GET",
|
||||
"headers": {
|
||||
"Authorization": "Bearer " + localStorage.getItem("token"),
|
||||
"userid": localStorage.getItem('id'),
|
||||
"year": year,
|
||||
},
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
return data;
|
||||
})
|
||||
}
|
||||
|
||||
export const getAllBooks = () => {
|
||||
return fetch('/api/books/all', {
|
||||
"method": "GET",
|
||||
|
|
|
@ -22,8 +22,6 @@
|
|||
|
||||
#DataTable{
|
||||
margin-bottom:0 !important;
|
||||
-webkit-box-shadow: 0px 1px 1px 1px #eee;
|
||||
box-shadow: 0px 1px 1px 1px #eee;
|
||||
}
|
||||
|
||||
#DataTable a {
|
||||
|
|
|
@ -4,17 +4,29 @@ import Books from "../components/Books";
|
|||
import Ratings from "../components/Ratings";
|
||||
import Stats from "../components/Stats";
|
||||
import Challenge from "../components/Challenge";
|
||||
import Sidebar from "../components/Sidebar";
|
||||
import * as moment from 'moment';
|
||||
import "../components/DataTables.css";
|
||||
moment.locale('nl');
|
||||
|
||||
const Dashboard = (props) => {
|
||||
const currentyear = new Date().getFullYear();
|
||||
const [year, setYear] = useState(currentyear);
|
||||
const [books, setBooks] = useState([]);
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [readingYears, setReadingYears] = useState([]);
|
||||
|
||||
const getData = async () => {
|
||||
const data = await import("../components/Data.js");
|
||||
const [data, functions] = await Promise.all([
|
||||
import("../components/Data.js"),
|
||||
import("../Functions.js")
|
||||
])
|
||||
const getYears = await data.getReadingYears();
|
||||
setReadingYears(getYears);
|
||||
|
||||
const getbooks = await data.getBooksByYear(year);
|
||||
setBooks(getbooks);
|
||||
|
||||
functions.initDataTable();
|
||||
}
|
||||
|
||||
const logout = () => {
|
||||
|
@ -44,24 +56,19 @@ const Dashboard = (props) => {
|
|||
|
||||
<div className="topbar_right">
|
||||
<ul>
|
||||
<li><i className="fas fa-book"></i></li>
|
||||
<li style={{ borderRight: "solid 1px rgba(255,255,255,0.5)", paddingRight: '20px' }}><i className="fas fa-tasks"></i></li>
|
||||
<li><i className="fas fa-book" onClick={() => {setShowModal(true)}}></i></li>
|
||||
{/* <li style={{ borderRight: "solid 1px rgba(255,255,255,0.5)", paddingRight: '20px' }}><i className="fas fa-tasks"></i></li> */}
|
||||
<li onClick={() => logout()}><i className="fas fa-power-off"></i></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{/* <Sidebar /> */}
|
||||
|
||||
<div className="content">
|
||||
<div className="container-fluid">
|
||||
{/* <div className="row">
|
||||
<div className="col-md-12">
|
||||
|
||||
</div>
|
||||
</div> */}
|
||||
<div className="row">
|
||||
<div className="col-md-8">
|
||||
<Stats year={year} />
|
||||
<Challenge year={year} />
|
||||
{/* <Challenge year={year} /> */}
|
||||
<Books year={year} />
|
||||
</div>
|
||||
|
||||
|
@ -72,6 +79,58 @@ const Dashboard = (props) => {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{ display: showModal === true ? 'block' : 'none' }} className="modal modal-books" tabIndex="-1" role="dialog">
|
||||
<div className="modal-dialog" role="document">
|
||||
<div className="modal-content">
|
||||
<button type="button" onClick={() => { setShowModal(false) }} className="close" data-dismiss="modal" aria-label="Close">
|
||||
<i class="fas fa-times-circle"></i>
|
||||
</button>
|
||||
<div className="DataTable_Container">
|
||||
<table id="DataTable" className="showHead table responsive nowrap" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Gelezen boeken</th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{books.map((book, i) => {
|
||||
var dotcolor = '';
|
||||
|
||||
if(book.genre === "Thriller"){
|
||||
dotcolor = '#404e67';
|
||||
}else if (book.genre === "Roman"){
|
||||
dotcolor = '#01a9ac';
|
||||
}else if(book.genre === 'Non-fictie'){
|
||||
dotcolor = '#64c5b1';
|
||||
}else{
|
||||
dotcolor = '#1ABB9C';
|
||||
}
|
||||
|
||||
return (
|
||||
<tr key={book.id}>
|
||||
<td>
|
||||
<div className="dotgenre" style={{ display: 'inline-block', verticalAlign: 'top', marginTop: '5px', marginRight: '10px', width: '10px', height: '10px', borderRadius: '100%', background: dotcolor }}></div>
|
||||
<div className="book-info" style={{ display: 'inline-block', verticalAlign: 'top' }}>
|
||||
{book.name}
|
||||
<div style={{ color: '#777' }} className="book-author">{book.author}</div>
|
||||
</div>
|
||||
</td>
|
||||
<td><i class='fas fa-star'></i> {book.rating}</td>
|
||||
<td style={{ textAlign: 'right' }}>
|
||||
<button onClick={() => delBook(book.id)} type="button" class="btn btn-danger"><i className="fa fa-trash"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
|
|
|
@ -680,6 +680,51 @@ html, body{
|
|||
padding: 0 10px 0 0px;
|
||||
}
|
||||
|
||||
/* .sidebar_books{
|
||||
background: #ffffff;
|
||||
height: 100vh;
|
||||
width: 300px;
|
||||
position: fixed;
|
||||
z-index: 10;
|
||||
right: 0;
|
||||
box-shadow: 0 0 20px rgba(0,0,0,.1);
|
||||
} */
|
||||
|
||||
.modal-books{
|
||||
background: rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.modal-books .modal-dialog{
|
||||
max-width:850px;
|
||||
width: 100%;
|
||||
padding: 30px;
|
||||
box-shadow: 0 0 20px rgba(0,0,0,.1);
|
||||
}
|
||||
|
||||
.modal-books .close{
|
||||
width: auto;
|
||||
position: absolute;
|
||||
right: -20px;
|
||||
top: -20px;
|
||||
}
|
||||
|
||||
.modal-books #DataTable thead th{
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.modal-books .DataTable_Container{
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.modal-books #DataTable button i{
|
||||
color: #ffffff;
|
||||
margin:auto;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Mobile app */
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,2 +1,2 @@
|
|||
/*! For license information please see src_Functions_js.js.LICENSE.txt */
|
||||
"use strict";(self.webpackChunkfrontend=self.webpackChunkfrontend||[]).push([["src_Functions_js"],{"./src/Functions.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "initDataTable": () => (/* binding */ initDataTable),\n/* harmony export */ "readCookie": () => (/* binding */ readCookie)\n/* harmony export */ });\n/* harmony import */ var datatables_net_dt__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! datatables.net-dt */ "./node_modules/datatables.net-dt/js/dataTables.dataTables.mjs");\n\nconst readCookie = name => {\n var nameEQ = name + "=";\n var ca = document.cookie.split(\';\');\n for (var i = 0; i < ca.length; i++) {\n var c = ca[i];\n while (c.charAt(0) == \' \') c = c.substring(1, c.length);\n if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);\n }\n return null;\n};\nconst initDataTable = () => {\n let table = new datatables_net_dt__WEBPACK_IMPORTED_MODULE_0__["default"](\'#DataTable\');\n table.destroy();\n setTimeout(() => {\n table = new datatables_net_dt__WEBPACK_IMPORTED_MODULE_0__["default"](\'#DataTable\', {\n columnDefs: [{\n width: \'20%\',\n targets: "_all"\n }],\n fixedColumns: true,\n language: {\n url: \'https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Dutch.json\',\n search: "",\n searchPlaceholder: "Zoeken"\n },\n dom: \'rt<"bottom"pl><"clear">\',\n order: [],\n "autoWidth": true\n });\n }, 300);\n};\n\n//# sourceURL=webpack://frontend/./src/Functions.js?')}}]);
|
||||
"use strict";(self.webpackChunkfrontend=self.webpackChunkfrontend||[]).push([["src_Functions_js"],{"./src/Functions.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "initDataTable": () => (/* binding */ initDataTable),\n/* harmony export */ "readCookie": () => (/* binding */ readCookie)\n/* harmony export */ });\n/* harmony import */ var datatables_net_dt__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! datatables.net-dt */ "./node_modules/datatables.net-dt/js/dataTables.dataTables.mjs");\n\nconst readCookie = name => {\n var nameEQ = name + "=";\n var ca = document.cookie.split(\';\');\n for (var i = 0; i < ca.length; i++) {\n var c = ca[i];\n while (c.charAt(0) == \' \') c = c.substring(1, c.length);\n if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);\n }\n return null;\n};\nconst initDataTable = () => {\n let table = new datatables_net_dt__WEBPACK_IMPORTED_MODULE_0__["default"](\'#DataTable\');\n table.destroy();\n setTimeout(() => {\n table = new datatables_net_dt__WEBPACK_IMPORTED_MODULE_0__["default"](\'#DataTable\', {\n autoWidth: true,\n language: {\n url: \'https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Dutch.json\',\n search: "",\n searchPlaceholder: "Zoeken"\n },\n dom: \'rt<"bottom"pl><"clear">\',\n order: []\n });\n }, 300);\n};\n\n//# sourceURL=webpack://frontend/./src/Functions.js?')}}]);
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue