1
1
Fork 0

API + Styling changes

This commit is contained in:
Jordy van Zeeland 2024-01-29 07:53:50 +01:00
parent 47ae9a846f
commit 195febfe17
12 changed files with 155 additions and 25 deletions

View File

@ -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']) 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: 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: else:
sql = 'SELECT * FROM api_books WHERE userid = ' + userid + ' ORDER BY readed' sql = 'SELECT * FROM api_books WHERE userid = ' + userid + ' ORDER BY readed'

View File

@ -5,6 +5,23 @@ from rest_framework.response import Response
from django.http import JsonResponse from django.http import JsonResponse
from .functions import isAuthorized, getBooksData, filterData 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 # Get all reading years
# ---------------------- # ----------------------

View File

@ -9,7 +9,7 @@ from .modules.predictions import *
urlpatterns = [ urlpatterns = [
path('books/all', getAllBooks), path('books/all', getAllBooks),
# path('books', getBooksByYear), path('books', getBooksByYear),
path('books/years', getYears), path('books/years', getYears),
path('books/stats', getStats), path('books/stats', getStats),
path('books/insert', addBook), path('books/insert', addBook),

View File

@ -16,18 +16,14 @@ export const initDataTable = () => {
table.destroy(); table.destroy();
setTimeout(() => { setTimeout(() => {
table = new DataTable('#DataTable', { table = new DataTable('#DataTable', {
columnDefs: [ autoWidth: true,
{ width: '20%', targets: "_all" }
],
fixedColumns: true,
language: { language: {
url: 'https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Dutch.json', url: 'https://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Dutch.json',
search: "", search: "",
searchPlaceholder: "Zoeken" searchPlaceholder: "Zoeken"
}, },
dom: 'rt<"bottom"pl><"clear">', dom: 'rt<"bottom"pl><"clear">',
order: [], order: []
"autoWidth": true
}); });
}, 300) }, 300)
} }

View File

@ -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 = () => { export const getAllBooks = () => {
return fetch('/api/books/all', { return fetch('/api/books/all', {
"method": "GET", "method": "GET",

View File

@ -22,8 +22,6 @@
#DataTable{ #DataTable{
margin-bottom:0 !important; margin-bottom:0 !important;
-webkit-box-shadow: 0px 1px 1px 1px #eee;
box-shadow: 0px 1px 1px 1px #eee;
} }
#DataTable a { #DataTable a {

View File

@ -4,17 +4,29 @@ import Books from "../components/Books";
import Ratings from "../components/Ratings"; import Ratings from "../components/Ratings";
import Stats from "../components/Stats"; import Stats from "../components/Stats";
import Challenge from "../components/Challenge"; 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 Dashboard = (props) => {
const currentyear = new Date().getFullYear(); const currentyear = new Date().getFullYear();
const [year, setYear] = useState(currentyear); const [year, setYear] = useState(currentyear);
const [books, setBooks] = useState([]);
const [showModal, setShowModal] = useState(false);
const [readingYears, setReadingYears] = useState([]); const [readingYears, setReadingYears] = useState([]);
const getData = async () => { 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(); const getYears = await data.getReadingYears();
setReadingYears(getYears); setReadingYears(getYears);
const getbooks = await data.getBooksByYear(year);
setBooks(getbooks);
functions.initDataTable();
} }
const logout = () => { const logout = () => {
@ -44,24 +56,19 @@ const Dashboard = (props) => {
<div className="topbar_right"> <div className="topbar_right">
<ul> <ul>
<li><i className="fas fa-book"></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 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> <li onClick={() => logout()}><i className="fas fa-power-off"></i></li>
</ul> </ul>
</div> </div>
</div> </div>
{/* <Sidebar /> */}
<div className="content"> <div className="content">
<div className="container-fluid"> <div className="container-fluid">
{/* <div className="row">
<div className="col-md-12">
</div>
</div> */}
<div className="row"> <div className="row">
<div className="col-md-8"> <div className="col-md-8">
<Stats year={year} /> <Stats year={year} />
<Challenge year={year} /> {/* <Challenge year={year} /> */}
<Books year={year} /> <Books year={year} />
</div> </div>
@ -72,6 +79,58 @@ const Dashboard = (props) => {
</div> </div>
</div> </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> </div>
</React.Fragment> </React.Fragment>
) )

View File

@ -680,6 +680,51 @@ html, body{
padding: 0 10px 0 0px; 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 */ /* Mobile app */
@media screen and (max-width: 768px) { @media screen and (max-width: 768px) {

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,2 @@
/*! For license information please see src_Functions_js.js.LICENSE.txt */ /*! 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