Compare commits
66 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b355680534 | ||
|
|
33998097a7 | ||
|
|
979870f41d | ||
|
|
dd575259b6 | ||
|
|
7512ed6257 | ||
|
|
07ae0d8396 | ||
|
|
6d27e5dc71 | ||
|
|
af654af1e4 | ||
|
|
0ae0ce3cc7 | ||
|
|
60fe2662a5 | ||
|
|
1caa6da2f0 | ||
|
|
99f2c94346 | ||
|
|
e8c58e0f7f | ||
| fe77894c0c | |||
| f3a1ebca28 | |||
|
|
5c2fdd202f | ||
|
|
452eff32bf | ||
|
|
dba5076107 | ||
|
|
ba35b25c60 | ||
|
|
57fa200f9b | ||
|
|
56e420198b | ||
|
|
dca6aa984e | ||
|
|
b2a6a0f7e1 | ||
|
|
d6b05ea986 | ||
|
|
3207920bac | ||
|
|
f8067dba8f | ||
|
|
08990e61dc | ||
|
|
1d5b6a04bd | ||
|
|
603a17b854 | ||
|
|
050638ae43 | ||
|
|
1bd2f84d91 | ||
|
|
0fa86b0755 | ||
|
|
c4c803cfad | ||
|
|
57950adbf0 | ||
|
|
7ab74205a1 | ||
|
|
8d415846e6 | ||
|
|
92600f8649 | ||
|
|
597510da52 | ||
|
|
ed066180bc | ||
|
|
50710b33b4 | ||
|
|
938b6e98d2 | ||
|
|
fb5f5a5bc0 | ||
|
|
1239995080 | ||
|
|
8e10d5fa1d | ||
|
|
26a1c0422f | ||
|
|
e0443811b1 | ||
|
|
41441db75d | ||
|
|
06e1599461 | ||
|
|
8036276187 | ||
|
|
141f533af6 | ||
|
|
a3af3aea05 | ||
|
|
af9196bca0 | ||
|
|
d88ca6d216 | ||
|
|
49b97ef0c2 | ||
|
|
76497e21c9 | ||
|
|
51de22aa67 | ||
|
|
d3fd938da3 | ||
|
|
d9fd74f422 | ||
|
|
ecbc5f9162 | ||
|
|
08e6bd431d | ||
|
|
2fabfb60f0 | ||
|
|
5a9360d10a | ||
|
|
581adb64a3 | ||
|
|
bc494a6133 | ||
|
|
f944e320ef | ||
|
|
204f8a4f22 |
27 changed files with 1425 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
__pycache__/
|
||||
venv/
|
||||
.vscode/
|
||||
28
app.py
Normal file
28
app.py
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
from flask import Flask, render_template, request
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.get("/")
|
||||
def get_owned():
|
||||
return render_template('owned.jinja')
|
||||
|
||||
@app.get("/wishlist")
|
||||
def get_wishlist():
|
||||
return render_template('wishlist.jinja')
|
||||
|
||||
@app.get("/boardgame")
|
||||
def get_boardgame():
|
||||
return render_template('boardgame.jinja')
|
||||
|
||||
|
||||
@app.get('/statistics')
|
||||
def get_statistics():
|
||||
return render_template('statistics.jinja')
|
||||
|
||||
@app.get('/incoming')
|
||||
def get_incoming():
|
||||
return render_template('incoming.jinja')
|
||||
|
||||
@app.get('/plays')
|
||||
def get_plays():
|
||||
return render_template('plays.jinja')
|
||||
7
requirements.txt
Normal file
7
requirements.txt
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
blinker==1.8.2
|
||||
click==8.1.7
|
||||
Flask==3.0.3
|
||||
itsdangerous==2.2.0
|
||||
Jinja2==3.1.4
|
||||
MarkupSafe==2.1.5
|
||||
Werkzeug==3.0.3
|
||||
6
static/css/bootstrap/bootstrap.min.css
vendored
Normal file
6
static/css/bootstrap/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
static/css/bootstrap/bootstrap.min.css.map
Normal file
1
static/css/bootstrap/bootstrap.min.css.map
Normal file
File diff suppressed because one or more lines are too long
19
static/css/datatables/datatables.min.css
vendored
Normal file
19
static/css/datatables/datatables.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
27
static/css/main.css
Normal file
27
static/css/main.css
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
body{
|
||||
padding-top: 100px;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 576px) {
|
||||
body {
|
||||
padding-top: 230px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.boardgame_statistic_card_image{
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.boardgame_play_card_image{
|
||||
width: 100%;
|
||||
height: 400px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.card-body{
|
||||
max-height: 550px;
|
||||
}
|
||||
BIN
static/favicon.ico
Normal file
BIN
static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 175 KiB |
221
static/javascript/boardgame.js
Normal file
221
static/javascript/boardgame.js
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
document.body.onload=loadGame()
|
||||
|
||||
const important_player_name_colors = {'Yarne':'black', 'Lore':'green', 'Lucas':'brown','Louize':'blue','Ruben':'purple', 'Ina':'orange', 'Matthias':'yellow','Kelly':'darkorange','Keanu':'darkblue'}
|
||||
|
||||
async function create_info_block(block_title, block_value){
|
||||
|
||||
var title = document.createElement('h2')
|
||||
title.textContent = block_title
|
||||
|
||||
var info_container = document.createElement('p')
|
||||
info_container.textContent = block_value
|
||||
|
||||
$('#info_block').append(title)
|
||||
$('#info_block').append(info_container)
|
||||
|
||||
}
|
||||
|
||||
async function create_info_meter(meter_title, min, max, value){
|
||||
var title = document.createElement('h2')
|
||||
title.textContent = meter_title
|
||||
|
||||
var meter_holder = document.createElement('div')
|
||||
meter_holder.classList.add('progress')
|
||||
|
||||
var meter = document.createElement('div')
|
||||
meter.classList.add('progress-bar')
|
||||
meter.role = 'progressbar'
|
||||
meter.style = `width: ${(value/max) * 100}%`
|
||||
meter.setAttribute('aria-valuenow', value)
|
||||
meter.setAttribute('aria-valuemin', min)
|
||||
meter.setAttribute('aria-valuemax', max)
|
||||
|
||||
if (value < max * 0.40){
|
||||
meter.classList.add('bg-success')
|
||||
}else if (value < max * 0.60){
|
||||
meter.classList.add('bg-warning')
|
||||
}else {
|
||||
meter.classList.add('bg-danger')
|
||||
}
|
||||
|
||||
meter_holder.appendChild(meter)
|
||||
|
||||
// meter.value = value
|
||||
// meter.min = min
|
||||
// meter.max = max
|
||||
|
||||
$('#info_block').append(title)
|
||||
$('#info_block').append(meter_holder)
|
||||
}
|
||||
|
||||
async function create_game_block(requested_game){
|
||||
$('#boardgame_image').attr('src', requested_game.image_url)
|
||||
|
||||
$('#boardgame_name').text(requested_game.name)
|
||||
|
||||
$('#boardgame_description').text(requested_game.description)
|
||||
|
||||
$('#boardgame_link').attr('href', 'https://boardgamegeek.com/boardgame/' + requested_game.id)
|
||||
}
|
||||
|
||||
async function create_playercount_vote_chart(requested_game){
|
||||
|
||||
const playercount_votes_chart = $('#playercount_votes_chart')
|
||||
const playercountVotes = requested_game.playercount_votes
|
||||
|
||||
const labels = playercountVotes.map(vote => vote.playercount);
|
||||
const bestData = playercountVotes.map(vote => vote.best);
|
||||
const recommendedData = playercountVotes.map(vote => vote.recommended);
|
||||
const notRecommendedData = playercountVotes.map(vote => vote.not_recommended);
|
||||
|
||||
const data = {
|
||||
labels: labels,
|
||||
datasets: [
|
||||
{
|
||||
label: 'Not Recommended',
|
||||
data: notRecommendedData,
|
||||
backgroundColor: 'rgba(255, 99, 132, 0.6)',
|
||||
},
|
||||
{
|
||||
label: 'Recommended',
|
||||
data: recommendedData,
|
||||
backgroundColor: 'rgba(75, 192, 192, 0.6)',
|
||||
},
|
||||
{
|
||||
label: 'Best',
|
||||
data: bestData,
|
||||
backgroundColor: 'rgba(50, 205, 50, 0.6)',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const config = {
|
||||
type: 'bar',
|
||||
data: data,
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'top',
|
||||
},
|
||||
title: {
|
||||
display: true,
|
||||
text: 'Player Count Votes'
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
x: {
|
||||
stacked: true,
|
||||
},
|
||||
y: {
|
||||
stacked: true,
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
new Chart(playercount_votes_chart, config);
|
||||
}
|
||||
|
||||
async function create_player_winrate_chart(requested_game){
|
||||
const playercount_votes_chart = $('#player_winrate_chart')
|
||||
const playercountVotes = requested_game.playercount_votes
|
||||
|
||||
// const labels = playercountVotes.map(vote => vote.playercount);
|
||||
// const bestData = playercountVotes.map(vote => vote.best);
|
||||
// const recommendedData = playercountVotes.map(vote => vote.recommended);
|
||||
// const notRecommendedData = playercountVotes.map(vote => vote.not_recommended);
|
||||
|
||||
const data_url = api_url + `/statistics/winrate_over_time?day_step=30&boardgame_id=${requested_game.id}`
|
||||
const data_request = await makeRequest(data_url)
|
||||
|
||||
let datasets = []
|
||||
|
||||
let players_who_played_game = [];
|
||||
|
||||
for (const play of requested_game.plays){
|
||||
for (const player of play.players){
|
||||
if (!players_who_played_game.includes(player.name)){
|
||||
players_who_played_game.push(player.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const [playername, color] of Object.entries(important_player_name_colors)){
|
||||
|
||||
if (players_who_played_game.includes(playername)){
|
||||
let dataset = {
|
||||
label: playername,
|
||||
data: Object.values(data_request[playername].result),
|
||||
borderColor: color
|
||||
}
|
||||
|
||||
datasets.push(dataset)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const labels = Object.keys(data_request[Object.keys(data_request)[0]].result)
|
||||
|
||||
const data = {
|
||||
labels: labels,
|
||||
datasets: datasets
|
||||
};
|
||||
|
||||
const config = {
|
||||
type: 'line',
|
||||
data: data,
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
offset: true,
|
||||
ticks:{
|
||||
format:{
|
||||
style: 'percent'
|
||||
}
|
||||
}
|
||||
},
|
||||
x: {
|
||||
offset: true
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
new Chart(playercount_votes_chart, config);
|
||||
}
|
||||
|
||||
async function loadGame() {
|
||||
let params = new URLSearchParams(document.location.search);
|
||||
let boardgame_id = params.get("id");
|
||||
|
||||
var loadGameURL = api_url + '/boardgame?id=' + boardgame_id
|
||||
var requested_game = await makeRequest(loadGameURL)
|
||||
|
||||
create_game_block(requested_game)
|
||||
|
||||
create_info_block('Spelers', requested_game.min_players != requested_game.max_players ? `${requested_game.min_players} - ${requested_game.max_players}` : requested_game.min_players)
|
||||
|
||||
create_info_meter('Moeilijkheid', 1, 5, requested_game.weight)
|
||||
|
||||
create_info_block(requested_game.designers.length > 1 ? 'Designers' : 'Designer', requested_game.designers.map(designer => designer.name).join(' - '))
|
||||
|
||||
create_info_block(requested_game.artists.length > 1 ? 'Artiesten' : 'Artiest', requested_game.artists.map(artist => artist.name).join(' - '))
|
||||
|
||||
if (requested_game.owned_info != null){
|
||||
let acquisition_date = new Date(requested_game.owned_info.acquisition_date)
|
||||
|
||||
const date_formatter = new Intl.DateTimeFormat('nl-BE', { dateStyle: 'short' });
|
||||
acquisition_date = date_formatter.format(acquisition_date)
|
||||
|
||||
create_info_block('Datum gekocht', acquisition_date)
|
||||
}
|
||||
|
||||
create_info_block('Aantal keer gespeeld', requested_game.plays.length)
|
||||
|
||||
create_playercount_vote_chart(requested_game)
|
||||
|
||||
create_player_winrate_chart(requested_game)
|
||||
|
||||
}
|
||||
20
static/javascript/chart/chart.js
Normal file
20
static/javascript/chart/chart.js
Normal file
File diff suppressed because one or more lines are too long
1
static/javascript/chart/chart.umd.js.map
Normal file
1
static/javascript/chart/chart.umd.js.map
Normal file
File diff suppressed because one or more lines are too long
7
static/javascript/chart/chartjs-plugin-datalabels.min.js
vendored
Normal file
7
static/javascript/chart/chartjs-plugin-datalabels.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
22
static/javascript/datatables/datatables.min.js
vendored
Normal file
22
static/javascript/datatables/datatables.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
0
static/javascript/incoming.js
Normal file
0
static/javascript/incoming.js
Normal file
2
static/javascript/jquery/jquery-3.7.1.min.js
vendored
Normal file
2
static/javascript/jquery/jquery-3.7.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
14
static/javascript/main.js
Normal file
14
static/javascript/main.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
const api_url = "https://api.bordspellen.yarnecoppens.com"
|
||||
|
||||
var all_owned_games
|
||||
|
||||
async function makeRequest(url) {
|
||||
try {
|
||||
const url_request = new Request(url)
|
||||
const response = await fetch(url_request);
|
||||
const result = await response.json();
|
||||
return result
|
||||
} catch (error) {
|
||||
console.error("Error:", error);
|
||||
}
|
||||
}
|
||||
109
static/javascript/owned.js
Normal file
109
static/javascript/owned.js
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
document.body.onload=loadOwnedGames()
|
||||
|
||||
document.getElementById('owned_nav').classList.add('active')
|
||||
|
||||
async function loadOwnedGames() {
|
||||
|
||||
const name_input = document.getElementById("name_input")
|
||||
const player_amount_input = document.getElementById("player_amount_input")
|
||||
|
||||
var boardgame_datatable = new DataTable('.boardgame_table', {
|
||||
"pageLength":-1,
|
||||
"bLengthChange": false,
|
||||
"bPaginate": false,
|
||||
"info": false,
|
||||
ajax: {
|
||||
url: api_url + '/owned?filter_expansions_out=true',
|
||||
dataSrc: ''
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
data: 'thumbnail_url',
|
||||
render: function (data,type){
|
||||
return '<img src="' + data + '" class="img-fluid" />'
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'name'
|
||||
},
|
||||
{
|
||||
data: 'min_players',
|
||||
render: function(data,type,row){
|
||||
if (row.min_players != row.max_players){
|
||||
return row.min_players + '-' + row.max_players
|
||||
}else{
|
||||
return row.min_players
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'min_playing_time',
|
||||
render: function(data,type,row){
|
||||
if (row.min_playing_time != row.max_playing_time){
|
||||
return row.min_playing_time + '-' + row.max_playing_time
|
||||
}else{
|
||||
return row.min_playing_time
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'weight'
|
||||
}
|
||||
],
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 'no-sort', orderable: false
|
||||
},
|
||||
{
|
||||
targets: '_all',
|
||||
orderSequence: [ 'asc', 'desc' ]
|
||||
}
|
||||
],
|
||||
order: [[1, 'asc']]
|
||||
});
|
||||
|
||||
// Custom range filtering function
|
||||
boardgame_datatable.search.fixed('range', function (searchStr, data, index) {
|
||||
|
||||
function isCorrectPlayerAmount(player_amount_wanted, min_players, max_players){
|
||||
if ((player_amount_wanted >= min_players && player_amount_wanted <= max_players) || isNaN(player_amount_wanted)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function isCorrectName(game_name_wanted, game_name){
|
||||
if (game_name.includes(game_name_wanted) || game_name_wanted == ""){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
var player_amount_wanted = parseInt(player_amount_input.value, 10);
|
||||
var min_players = parseFloat(data['min_players'])
|
||||
var max_players = parseFloat(data['max_players'])
|
||||
|
||||
var game_name_wanted = name_input.value.toLowerCase()
|
||||
var game_name = data['name'].toLowerCase()
|
||||
|
||||
if (isCorrectPlayerAmount(player_amount_wanted, min_players, max_players) && isCorrectName(game_name_wanted, game_name)){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
player_amount_input.addEventListener('input', function () {
|
||||
boardgame_datatable.draw();
|
||||
});
|
||||
|
||||
name_input.addEventListener('input', function () {
|
||||
boardgame_datatable.draw();
|
||||
});
|
||||
|
||||
|
||||
$('.boardgame_table').on('click', 'tbody tr', function() {
|
||||
var boardgame_id = boardgame_datatable.row(this).data().id;
|
||||
window.location.href = "/boardgame?id=" + boardgame_id
|
||||
})
|
||||
|
||||
}
|
||||
101
static/javascript/plays.js
Normal file
101
static/javascript/plays.js
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
document.body.onload=loadPlays()
|
||||
document.getElementById('plays_nav').classList.add('active')
|
||||
|
||||
async function loadPlays() {
|
||||
|
||||
function createPlayCard(play){
|
||||
|
||||
const card_div = document.createElement('div')
|
||||
card_div.classList.add("card")
|
||||
card_div.classList.add('h-100')
|
||||
|
||||
const boardgame_image_linked = document.createElement('a')
|
||||
boardgame_image_linked.setAttribute('href', '/boardgame?id=' + play.boardgame.id)
|
||||
|
||||
const card_image = document.createElement('img')
|
||||
card_image.src = play.boardgame.image_url
|
||||
card_image.classList.add('card-img-top')
|
||||
card_image.classList.add('boardgame_play_card_image')
|
||||
|
||||
boardgame_image_linked.appendChild(card_image)
|
||||
|
||||
const card_body = document.createElement('div')
|
||||
card_body.classList.add('card-body')
|
||||
|
||||
const card_title = document.createElement('h4')
|
||||
card_title.innerHTML = play.boardgame.name
|
||||
card_title.classList.add('card-title')
|
||||
|
||||
const player_names = document.createElement('p')
|
||||
player_names.classList.add('card-text')
|
||||
|
||||
for (let player_index in play.players){
|
||||
const player = play.players[player_index]
|
||||
const player_div = document.createElement('div')
|
||||
player_div.innerHTML = player.name
|
||||
|
||||
if (player.has_won) {
|
||||
player_div.style.color = "green"
|
||||
}
|
||||
|
||||
player_names.appendChild(player_div)
|
||||
}
|
||||
|
||||
card_body.appendChild(card_title)
|
||||
card_body.appendChild(player_names)
|
||||
|
||||
card_div.appendChild(boardgame_image_linked)
|
||||
card_div.appendChild(card_body)
|
||||
|
||||
return card_div
|
||||
|
||||
}
|
||||
|
||||
const all_plays = await makeRequest(api_url + '/plays?filter_expansions_out=true')
|
||||
|
||||
|
||||
const row = document.createElement('row')
|
||||
row.classList.add('row')
|
||||
row.classList.add('row-cols-1')
|
||||
row.classList.add('row-cols-md-4')
|
||||
|
||||
for (let play_index in all_plays){
|
||||
let current_play = all_plays[play_index]
|
||||
|
||||
const column = document.createElement('div')
|
||||
column.classList.add('col')
|
||||
|
||||
let card = createPlayCard(current_play)
|
||||
|
||||
column.appendChild(card)
|
||||
|
||||
row.appendChild(column)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// for (let row_number = 0; row_number < rows_needed; row_number++){
|
||||
// const row_div = document.createElement('div')
|
||||
// row_div.className = 'row'
|
||||
// for (let column_number = 0; column_number < MAX_COLUMNS; column_number++) {
|
||||
// if(((row_number * MAX_COLUMNS) + column_number) == all_plays.length){
|
||||
// break
|
||||
// }
|
||||
// const column_div = document.createElement('div')
|
||||
// column_div.className = "col-sm-" + column_width
|
||||
|
||||
// const current_play = all_plays[(row_number * MAX_COLUMNS) + column_number]
|
||||
// const play_card = createPlayCard(current_play)
|
||||
|
||||
// column_div.appendChild(play_card)
|
||||
// row_div.appendChild(column_div)
|
||||
// }
|
||||
// document.body.appendChild(row_div)
|
||||
// }
|
||||
|
||||
document.body.append(row)
|
||||
|
||||
document.getElementById('plays_loading_spinner').remove()
|
||||
|
||||
}
|
||||
524
static/javascript/statistics.js
Normal file
524
static/javascript/statistics.js
Normal file
|
|
@ -0,0 +1,524 @@
|
|||
document.body.onload=loadStatistics()
|
||||
document.getElementById('statistics_nav').classList.add('active')
|
||||
|
||||
const important_player_name_colors = {'Yarne':'black', 'Lore':'green', 'Lucas':'brown','Louize':'blue','Ruben':'purple', 'Ina':'orange', 'Matthias':'yellow','Kelly':'darkorange','Keanu':'darkblue'}
|
||||
|
||||
function create_statistic_card(col_number = null){
|
||||
function create_statistic_card_col(){
|
||||
const col = document.createElement('col')
|
||||
if (col_number == null){
|
||||
col.classList.add('col-12')
|
||||
col.classList.add('col-md-6')
|
||||
}else{
|
||||
col.classList.add('col-' + col_number * 2)
|
||||
col.classList.add('col-md-'+col_number)
|
||||
}
|
||||
|
||||
|
||||
const card = document.createElement('div')
|
||||
card.classList.add('card')
|
||||
card.classList.add('h-100')
|
||||
|
||||
col.appendChild(card)
|
||||
|
||||
return col
|
||||
}
|
||||
|
||||
let statistic_row = document.getElementById('statistic_row')
|
||||
|
||||
const statistic_card_col = create_statistic_card_col()
|
||||
const statistic_card = statistic_card_col.firstChild
|
||||
statistic_row.appendChild(statistic_card_col)
|
||||
|
||||
return statistic_card
|
||||
|
||||
}
|
||||
|
||||
async function create_games_over_time_chart(){
|
||||
|
||||
let games_over_time_statistic = await makeRequest(api_url + '/statistics/amount_of_games_over_time?day_step=30')
|
||||
let games_over_time_statistic_no_expanions = await makeRequest(api_url + '/statistics/amount_of_games_over_time?day_step=30&filter_expansions_out=true')
|
||||
let games_over_time_statistic_only_expanions = await makeRequest(api_url + '/statistics/amount_of_games_over_time?day_step=30&only_expansions=true')
|
||||
|
||||
const card_to_fill = create_statistic_card(12)
|
||||
const chart_canvas_container = document.createElement('div')
|
||||
chart_canvas_container.classList.add('card-body')
|
||||
chart_canvas_container.classList.add('card-img-top')
|
||||
|
||||
const chart_canvas = document.createElement('canvas')
|
||||
chart_canvas.classList.add('chart_visual')
|
||||
|
||||
|
||||
chart_canvas_container.appendChild(chart_canvas)
|
||||
|
||||
|
||||
|
||||
new Chart(chart_canvas, {
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: Object.keys(games_over_time_statistic.result),
|
||||
datasets: [{
|
||||
label: games_over_time_statistic.name,
|
||||
data: Object.values(games_over_time_statistic.result),
|
||||
borderWidth: 1,
|
||||
type: 'line'
|
||||
},
|
||||
{
|
||||
label: "Base games",
|
||||
data: Object.values(games_over_time_statistic_no_expanions.result),
|
||||
borderWidth: 1
|
||||
},
|
||||
{
|
||||
label: "Expansions",
|
||||
data: Object.values(games_over_time_statistic_only_expanions.result),
|
||||
borderWidth: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const card_footer = document.createElement('div')
|
||||
card_footer.classList.add('card-header')
|
||||
card_footer.classList.add('text-muted')
|
||||
card_footer.innerHTML = games_over_time_statistic.name
|
||||
|
||||
card_to_fill.appendChild(card_footer)
|
||||
card_to_fill.appendChild(chart_canvas_container)
|
||||
}
|
||||
|
||||
async function create_line_chart(statistic_data, name=''){
|
||||
if (name == ""){
|
||||
statistic_name = statistic_data.name
|
||||
}else{
|
||||
statistic_name = name
|
||||
}
|
||||
|
||||
const card_to_fill = create_statistic_card()
|
||||
|
||||
const chart_canvas_container = document.createElement('div')
|
||||
chart_canvas_container.classList.add('card-body')
|
||||
chart_canvas_container.classList.add('card-img-top')
|
||||
|
||||
const chart_canvas = document.createElement('canvas')
|
||||
chart_canvas.classList.add('chart_visual')
|
||||
|
||||
chart_canvas_container.appendChild(chart_canvas)
|
||||
|
||||
const highest_bar_value = Math.max(...Object.values(statistic_data.result))
|
||||
|
||||
let grid_offset = 0
|
||||
|
||||
if (highest_bar_value > 10000){
|
||||
grid_offset = 25000
|
||||
}else if(highest_bar_value > 1000){
|
||||
grid_offset = 2500
|
||||
}else if(highest_bar_value > 100){
|
||||
grid_offset = 250
|
||||
}else if(highest_bar_value > 10){
|
||||
grid_offset = 25
|
||||
}else if(highest_bar_value > 2){
|
||||
grid_offset = 2.5
|
||||
}else{
|
||||
grid_offset = 1.25
|
||||
}
|
||||
|
||||
new Chart(chart_canvas, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: Object.keys(statistic_data.result),
|
||||
datasets: [{
|
||||
label: statistic_data.name,
|
||||
data: Object.values(statistic_data.result),
|
||||
borderWidth: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
max: Math.ceil((highest_bar_value) / grid_offset) * grid_offset
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const card_footer = document.createElement('div')
|
||||
card_footer.classList.add('card-header')
|
||||
card_footer.classList.add('text-muted')
|
||||
card_footer.innerHTML = statistic_name
|
||||
|
||||
card_to_fill.appendChild(card_footer)
|
||||
card_to_fill.appendChild(chart_canvas_container)
|
||||
}
|
||||
|
||||
async function create_multi_line_chart(statistic_data, name=''){
|
||||
if (name == ""){
|
||||
statistic_name = statistic_data.name
|
||||
}else{
|
||||
statistic_name = name
|
||||
}
|
||||
|
||||
const card_to_fill = create_statistic_card(12)
|
||||
|
||||
const chart_canvas_container = document.createElement('div')
|
||||
chart_canvas_container.classList.add('card-body')
|
||||
chart_canvas_container.classList.add('card-img-top')
|
||||
|
||||
const chart_canvas = document.createElement('canvas')
|
||||
chart_canvas.classList.add('chart_visual')
|
||||
|
||||
chart_canvas_container.appendChild(chart_canvas)
|
||||
|
||||
let own_datasets = []
|
||||
let all_results = []
|
||||
let all_dates = []
|
||||
|
||||
for (key in statistic_data){
|
||||
|
||||
for (date in statistic_data[key].result){
|
||||
if (statistic_data[key].result[date] == 0){
|
||||
statistic_data[key].result[date] = null
|
||||
}
|
||||
}
|
||||
if (!Object.keys(important_player_name_colors).includes(key)){
|
||||
dataset = {
|
||||
label: key,
|
||||
data: Object.values(statistic_data[key].result)
|
||||
}
|
||||
}else{
|
||||
dataset = {
|
||||
label: key,
|
||||
data: Object.values(statistic_data[key].result),
|
||||
borderColor: important_player_name_colors[key]
|
||||
}
|
||||
}
|
||||
|
||||
own_datasets.push(dataset)
|
||||
for (result_value in Object.values(statistic_data[key].result)){
|
||||
all_results.push(result_value)
|
||||
}
|
||||
for (date in statistic_data[key].result){
|
||||
if (!all_dates.includes(date)){
|
||||
all_dates.push(date)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new Chart(chart_canvas, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: all_dates,
|
||||
datasets: own_datasets
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
offset: true
|
||||
},
|
||||
x: {
|
||||
offset: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const card_footer = document.createElement('div')
|
||||
card_footer.classList.add('card-header')
|
||||
card_footer.classList.add('text-muted')
|
||||
card_footer.innerHTML = statistic_name
|
||||
|
||||
card_to_fill.appendChild(card_footer)
|
||||
card_to_fill.appendChild(chart_canvas_container)
|
||||
}
|
||||
|
||||
async function create_bar_chart(statistic_data, name=''){
|
||||
|
||||
if (name == ""){
|
||||
statistic_name = statistic_data.name
|
||||
}else{
|
||||
statistic_name = name
|
||||
}
|
||||
|
||||
const card_to_fill = create_statistic_card()
|
||||
|
||||
const chart_canvas_container = document.createElement('div')
|
||||
chart_canvas_container.classList.add('card-body')
|
||||
chart_canvas_container.classList.add('card-img-top')
|
||||
|
||||
const chart_canvas = document.createElement('canvas')
|
||||
chart_canvas.classList.add('chart_visual')
|
||||
|
||||
chart_canvas_container.appendChild(chart_canvas)
|
||||
|
||||
const highest_bar_value = Math.max(...Object.values(statistic_data.result))
|
||||
|
||||
let grid_offset = 0
|
||||
|
||||
if (highest_bar_value > 10000){
|
||||
grid_offset = 25000
|
||||
}else if(highest_bar_value > 1000){
|
||||
grid_offset = 2500
|
||||
}else if(highest_bar_value > 100){
|
||||
grid_offset = 250
|
||||
}else{
|
||||
grid_offset = 25
|
||||
}
|
||||
|
||||
new Chart(chart_canvas, {
|
||||
plugins: [ChartDataLabels],
|
||||
type: 'bar',
|
||||
data: {
|
||||
labels: Object.keys(statistic_data.result),
|
||||
datasets: [{
|
||||
label: statistic_data.name,
|
||||
data: Object.values(statistic_data.result),
|
||||
borderWidth: 1
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true,
|
||||
max: Math.ceil((highest_bar_value) / grid_offset) * grid_offset
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
datalabels: {
|
||||
anchor: 'end',
|
||||
align: 'end'
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const card_footer = document.createElement('div')
|
||||
card_footer.classList.add('card-header')
|
||||
card_footer.classList.add('text-muted')
|
||||
card_footer.innerHTML = statistic_name
|
||||
|
||||
card_to_fill.appendChild(card_footer)
|
||||
card_to_fill.appendChild(chart_canvas_container)
|
||||
|
||||
|
||||
}
|
||||
|
||||
async function create_multiple_boardgame_chart(statistic_data, name = '', include_footer = false, footer_preamble = ''){
|
||||
function create_boardgame_image_grid_row(boardgames, include_footer, footer_data, footer_preamble){
|
||||
|
||||
const row_container = document.createElement('div')
|
||||
row_container.classList.add('container')
|
||||
|
||||
const row = document.createElement('div')
|
||||
row.classList.add('row')
|
||||
row.classList.add('row-cols-1')
|
||||
row.classList.add('row-cols-md-3')
|
||||
row.classList.add('g-4')
|
||||
|
||||
|
||||
for (let boardgame_index in boardgames){
|
||||
let current_boardgame = boardgames[boardgame_index]
|
||||
|
||||
const column = document.createElement('div')
|
||||
column.classList.add('col')
|
||||
|
||||
const boardgame_card = document.createElement('div')
|
||||
boardgame_card.classList.add('card')
|
||||
boardgame_card.classList.add('h-100')
|
||||
|
||||
const boardgame_imaged_linked = document.createElement('a')
|
||||
boardgame_imaged_linked.setAttribute('href', '/boardgame?id=' + current_boardgame.id)
|
||||
|
||||
const boardgame_image = document.createElement('img')
|
||||
boardgame_image.src = current_boardgame.thumbnail_url
|
||||
boardgame_image.classList.add('card-img-top')
|
||||
boardgame_image.classList.add('boardgame_statistic_card_image')
|
||||
|
||||
boardgame_imaged_linked.appendChild(boardgame_image)
|
||||
|
||||
const boardgame_card_body = document.createElement('div')
|
||||
boardgame_card_body.classList.add('card-body')
|
||||
|
||||
|
||||
const boardgame_title = document.createElement('h6')
|
||||
boardgame_title.innerHTML = current_boardgame.name
|
||||
boardgame_title.classList.add('card-title')
|
||||
|
||||
boardgame_card_body.appendChild(boardgame_title)
|
||||
|
||||
if (include_footer){
|
||||
const boardgame_footer = document.createElement('p')
|
||||
boardgame_footer.innerHTML = footer_preamble + footer_data[current_boardgame.id]
|
||||
boardgame_footer.classList.add('card-text')
|
||||
boardgame_card_body.appendChild(boardgame_footer)
|
||||
}
|
||||
|
||||
boardgame_card.append(boardgame_imaged_linked)
|
||||
boardgame_card.append(boardgame_card_body)
|
||||
|
||||
column.appendChild(boardgame_card)
|
||||
|
||||
row.appendChild(column)
|
||||
|
||||
}
|
||||
|
||||
return row
|
||||
|
||||
}
|
||||
|
||||
if (name == ""){
|
||||
statistic_name = statistic_data.name
|
||||
}else{
|
||||
statistic_name = name
|
||||
}
|
||||
|
||||
const card_to_fill = create_statistic_card()
|
||||
|
||||
const card_header = document.createElement('div')
|
||||
card_header.classList.add('card-header')
|
||||
|
||||
const card_footer_text = document.createElement('div')
|
||||
card_footer_text.classList.add('text-muted')
|
||||
card_footer_text.innerHTML = statistic_name
|
||||
card_header.appendChild(card_footer_text)
|
||||
|
||||
card_to_fill.appendChild(card_header)
|
||||
|
||||
const boardgame_image_container = document.createElement('div')
|
||||
boardgame_image_container.classList.add('card-body')
|
||||
boardgame_image_container.classList.add('chart_visual')
|
||||
boardgame_image_container.classList.add('container-fluid')
|
||||
boardgame_image_container.classList.add('overflow-auto')
|
||||
|
||||
const boardgames_to_grid = statistic_data.games
|
||||
|
||||
const footer_data = statistic_data.result
|
||||
|
||||
|
||||
|
||||
// if (footer_attribute != ''){
|
||||
// for (boardgame_index in boardgames_to_grid){
|
||||
// let footer_string = footer_attribute_to_value(boardgames_to_grid[boardgame_index], footer_attribute)
|
||||
// if (footer_preamble != ''){
|
||||
// footer_string = footer_preamble + footer_string
|
||||
// }
|
||||
// footer_data.push(footer_string)
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
const row = create_boardgame_image_grid_row(boardgames_to_grid, include_footer, footer_data, footer_preamble)
|
||||
|
||||
boardgame_image_container.appendChild(row)
|
||||
|
||||
card_to_fill.appendChild(boardgame_image_container)
|
||||
|
||||
|
||||
}
|
||||
|
||||
async function create_basic_statistic_chart(statistic_data, name='', preamble=''){
|
||||
|
||||
if (name == ""){
|
||||
statistic_name = statistic_data.name
|
||||
}else{
|
||||
statistic_name = name
|
||||
}
|
||||
|
||||
const card_to_fill = create_statistic_card(3)
|
||||
|
||||
const card_header = document.createElement('div')
|
||||
card_header.classList.add('card-header')
|
||||
card_header.classList.add('text-muted')
|
||||
card_header.innerHTML = statistic_name
|
||||
|
||||
card_to_fill.appendChild(card_header)
|
||||
|
||||
const card_body = document.createElement('div')
|
||||
card_body.classList.add('card-body')
|
||||
|
||||
const card_title = document.createElement('h5')
|
||||
card_title.classList.add('card-title')
|
||||
card_title.innerHTML = preamble + statistic_data.result
|
||||
|
||||
card_body.appendChild(card_title)
|
||||
|
||||
card_to_fill.appendChild(card_header)
|
||||
card_to_fill.appendChild(card_body)
|
||||
|
||||
}
|
||||
|
||||
async function loadStatistics(){
|
||||
|
||||
const amount_of_games_statistic_data = await makeRequest(api_url+'/statistics/amount_of_games')
|
||||
create_basic_statistic_chart(amount_of_games_statistic_data, 'Spellen in bezit')
|
||||
|
||||
const total_collection_cost_statistic_data = await makeRequest(api_url+'/statistics/total_collection_cost')
|
||||
total_collection_cost_statistic_data.result = total_collection_cost_statistic_data.result.toFixed(2)
|
||||
create_basic_statistic_chart(total_collection_cost_statistic_data, 'Totale kost van spellen in bezit', '\u20AC ')
|
||||
|
||||
const h_index_statistic_data = await makeRequest(api_url+'/statistics/h_index')
|
||||
create_basic_statistic_chart(h_index_statistic_data, 'H-index')
|
||||
|
||||
|
||||
|
||||
//Seperate because of multiple data
|
||||
await create_games_over_time_chart()
|
||||
|
||||
const winrate_over_time_statistic_data = await makeRequest(api_url + '/statistics/winrate_over_time?day_step=30')
|
||||
for (let player_name in winrate_over_time_statistic_data){
|
||||
if (!Object.keys(important_player_name_colors).includes(player_name)){
|
||||
delete winrate_over_time_statistic_data[player_name]
|
||||
}else{
|
||||
for (date_key in winrate_over_time_statistic_data[player_name].result)
|
||||
winrate_over_time_statistic_data[player_name].result[date_key] *= 100
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
create_multi_line_chart(winrate_over_time_statistic_data, 'Winrate van spelers over tijd')
|
||||
|
||||
|
||||
const games_played_per_year_statistic_data = await makeRequest(api_url + '/statistics/games_played_per_year?filter_expansions_out=true')
|
||||
create_bar_chart(games_played_per_year_statistic_data, 'Spellen gespeeld per jaar')
|
||||
|
||||
const winrate_statistic_data = await makeRequest(api_url + '/statistics/winrate')
|
||||
for (let player_name in winrate_statistic_data.result){
|
||||
if (!Object.keys(important_player_name_colors).includes(player_name)){
|
||||
delete winrate_statistic_data.result[player_name]
|
||||
}else{
|
||||
winrate_statistic_data.result[player_name] *= 100
|
||||
winrate_statistic_data.result[player_name] = winrate_statistic_data.result[player_name].toFixed(2)
|
||||
}
|
||||
}
|
||||
|
||||
create_bar_chart(winrate_statistic_data, 'Winrate van spelers')
|
||||
|
||||
const most_expensive_games_statistic_data = await makeRequest(api_url+'/statistics/most_expensive_games?top_amount=6')
|
||||
create_multiple_boardgame_chart(most_expensive_games_statistic_data, 'Duurste spellen', true, '\u20AC ')
|
||||
|
||||
const cheapest_per_play_games_statistic_data = await makeRequest(api_url+'/statistics/cheapest_per_play?top_amount=6')
|
||||
for (let boardgame_id_result in cheapest_per_play_games_statistic_data.result){
|
||||
cheapest_per_play_games_statistic_data.result[boardgame_id_result] = cheapest_per_play_games_statistic_data.result[boardgame_id_result].toFixed(2)
|
||||
}
|
||||
create_multiple_boardgame_chart(cheapest_per_play_games_statistic_data, 'Goedkoopste per sessie', true, '\u20AC ')
|
||||
|
||||
const shelf_of_shame_statistic_data = await makeRequest(api_url + '/statistics/shelf_of_shame')
|
||||
create_multiple_boardgame_chart(shelf_of_shame_statistic_data, 'Shelf of Shame', false)
|
||||
|
||||
const most_bought_from_designer_statistic_data = await makeRequest(api_url + '/statistics/most_bought_designer?filter_expansions_out=true')
|
||||
create_multiple_boardgame_chart(most_bought_from_designer_statistic_data, 'Designer waarvan we het meeste hebben gekocht', true)
|
||||
|
||||
const most_bought_from_artist_statistic_data = await makeRequest(api_url + '/statistics/most_bought_artist?filter_expansions_out=true')
|
||||
create_multiple_boardgame_chart(most_bought_from_artist_statistic_data, 'Artiest waarvan we het meeste hebben gekocht', true)
|
||||
|
||||
|
||||
}
|
||||
69
static/javascript/wishlist.js
Normal file
69
static/javascript/wishlist.js
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
document.body.onload=loadWishlistedGames()
|
||||
document.getElementById('wishlist_nav').classList.add('active')
|
||||
|
||||
async function loadWishlistedGames() {
|
||||
|
||||
var wishlist_priorities = [1,2,3,4]
|
||||
|
||||
jQuery.each(wishlist_priorities, function(index, item){
|
||||
|
||||
var boardgame_datatable = new DataTable('#wishlist_table'+item, {
|
||||
ajax: {
|
||||
url: api_url + '/wishlist?priority='+item,
|
||||
dataSrc: ''
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
data: 'wishlist_info.wishlist_priority'
|
||||
},
|
||||
{
|
||||
data: 'thumbnail_url',
|
||||
render: function (data,type){
|
||||
return '<img src="' + data + '" class="img-fluid" />'
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'name'
|
||||
},
|
||||
{
|
||||
data: 'min_players',
|
||||
render: function(data,type,row){
|
||||
if (row.min_players != row.max_players){
|
||||
return row.min_players + '-' + row.max_players
|
||||
}else{
|
||||
return row.min_players
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'min_playing_time',
|
||||
render: function(data,type,row){
|
||||
if (row.min_playing_time != row.max_playing_time){
|
||||
return row.min_playing_time + '-' + row.max_playing_time
|
||||
}else{
|
||||
return row.min_playing_time
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 'weight'
|
||||
}
|
||||
],
|
||||
columnDefs: [
|
||||
{
|
||||
target: 0,
|
||||
visible: false
|
||||
},
|
||||
{ targets: 'no-sort', orderable: false }
|
||||
],
|
||||
order: [[2, 'asc']]
|
||||
});
|
||||
|
||||
$('#wishlist_table'+item).on('click', 'tbody tr', function() {
|
||||
var boardgame_id = boardgame_datatable.row(this).data().id;
|
||||
window.location.href = "/boardgame?id=" + boardgame_id
|
||||
})
|
||||
});
|
||||
|
||||
}
|
||||
59
templates/base.jinja
Normal file
59
templates/base.jinja
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE html>
|
||||
<html data-theme="light">
|
||||
|
||||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>
|
||||
Boardgame Site
|
||||
</title>
|
||||
|
||||
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}">
|
||||
<link href="{{ url_for('static', filename='css/bootstrap/bootstrap.min.css') }}" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<link href="{{ url_for('static', filename='css/datatables/datatables.min.css') }}" rel="stylesheet">
|
||||
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
|
||||
|
||||
<script src="{{ url_for('static', filename='javascript/jquery/jquery-3.7.1.min.js') }}" defer></script>
|
||||
<script src="{{ url_for('static', filename='javascript/datatables/datatables.min.js') }}" defer></script>
|
||||
<script src="{{ url_for('static', filename='javascript/chart/chart.js') }}" defer></script>
|
||||
<script src="{{ url_for('static', filename='javascript/chart/chartjs-plugin-datalabels.min.js') }}" defer></script>
|
||||
|
||||
<script defer src="https://umami.yarnecoppens.com/script.js" data-website-id="fe668e9a-4434-48ed-bffb-6d1001f494c8"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-expand-sm bg-dark navbar-dark fixed-top">
|
||||
<div class="container-fluid">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a id="owned_nav" class="nav-link" href="{{ url_for('get_owned') }}">Collectie</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a id="wishlist_nav" class="nav-link" href="{{ url_for('get_wishlist') }}">Wishlist</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a id="statistics_nav" class="nav-link" href="{{ url_for('get_statistics') }}">Statistieken</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a id="plays_nav" class="nav-link" href="{{ url_for('get_plays') }}">Gespeeld</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link disabled" href="#">Disabled</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{% block body_block %}
|
||||
|
||||
{% endblock body_block %}
|
||||
|
||||
|
||||
<script src="{{ url_for('static', filename='javascript/main.js') }}" defer></script>
|
||||
{% block extra_js_files %}
|
||||
|
||||
{% endblock extra_js_files%}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
31
templates/boardgame.jinja
Normal file
31
templates/boardgame.jinja
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{% extends "base.jinja" %}
|
||||
|
||||
{% block body_block %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
<div class="card">
|
||||
<img id="boardgame_image">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title" id="boardgame_name">John Doe</h4>
|
||||
<p class="card-text" id="boardgame_description">Some example text.</p>
|
||||
<a href="#" id="boardgame_link" class="btn btn-primary">Bekijk op BGG</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3" id="info_block">
|
||||
<h1>Info</h1>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<canvas id="playercount_votes_chart"></canvas>
|
||||
<canvas id="player_winrate_chart"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock body_block %}
|
||||
|
||||
{% block extra_js_files %}
|
||||
|
||||
<script src="{{ url_for('static', filename='javascript/boardgame.js') }}" defer></script>
|
||||
|
||||
{% endblock extra_js_files %}
|
||||
14
templates/incoming.jinja
Normal file
14
templates/incoming.jinja
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{% extends "base.jinja" %}
|
||||
|
||||
|
||||
{% block body_block %}
|
||||
|
||||
|
||||
|
||||
{% endblock body_block %}
|
||||
|
||||
{% block extra_js_files %}
|
||||
|
||||
<script src="{{ url_for('static', filename='javascript/incoming.js') }}" defer></script>
|
||||
|
||||
{% endblock extra_js_files %}
|
||||
31
templates/owned.jinja
Normal file
31
templates/owned.jinja
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{% extends "base.jinja" %}
|
||||
|
||||
|
||||
{% block body_block %}
|
||||
|
||||
<div class="form-group">
|
||||
<input class="form-control" id="name_input" placeholder="Spelnaam">
|
||||
<input type="number" class="form-control" id="player_amount_input" placeholder="Aantal spelers">
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped boardgame_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="no-sort">Thumbnail</th>
|
||||
<th scope="col">Naam</th>
|
||||
<th scope="col">Spelers</th>
|
||||
<th scope="col">Duratie</th>
|
||||
<th scope="col">Moeilijkheid</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{% endblock body_block %}
|
||||
|
||||
{% block extra_js_files %}
|
||||
|
||||
<script src="{{ url_for('static', filename='javascript/owned.js') }}" defer></script>
|
||||
|
||||
{% endblock extra_js_files %}
|
||||
11
templates/plays.jinja
Normal file
11
templates/plays.jinja
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{% extends "base.jinja" %}
|
||||
|
||||
{% block body_block %}
|
||||
<div id="plays_loading_spinner" class="spinner-border"></div>
|
||||
{% endblock body_block %}
|
||||
|
||||
{% block extra_js_files %}
|
||||
|
||||
<script src="{{ url_for('static', filename='javascript/plays.js') }}" defer></script>
|
||||
|
||||
{% endblock extra_js_files %}
|
||||
17
templates/statistics.jinja
Normal file
17
templates/statistics.jinja
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
{% extends "base.jinja" %}
|
||||
|
||||
|
||||
{% block body_block %}
|
||||
|
||||
<div class="container">
|
||||
<div id="statistic_row" class="row g-4 ">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock body_block %}
|
||||
|
||||
{% block extra_js_files %}
|
||||
|
||||
<script src="{{ url_for('static', filename='javascript/statistics.js') }}" defer></script>
|
||||
|
||||
{% endblock extra_js_files %}
|
||||
81
templates/wishlist.jinja
Normal file
81
templates/wishlist.jinja
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
{% extends "base.jinja" %}
|
||||
|
||||
|
||||
{% block body_block %}
|
||||
|
||||
<body onload="loadWishlistedGames()">
|
||||
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="wishlist_table1" class="table table-striped boardgame_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">wishlist_priority</th>
|
||||
<th scope="col" class="no-sort">Thumbnail</th>
|
||||
<th scope="col">Naam</th>
|
||||
<th scope="col">Spelers</th>
|
||||
<th scope="col">Duratie</th>
|
||||
<th scope="col">Moeilijkheid</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="wishlist_table2" class="table table-striped boardgame_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">wishlist_priority</th>
|
||||
<th scope="col" class="no-sort">Thumbnail</th>
|
||||
<th scope="col">Naam</th>
|
||||
<th scope="col">Spelers</th>
|
||||
<th scope="col">Duratie</th>
|
||||
<th scope="col">Moeilijkheid</th>
|
||||
</tr>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="wishlist_table3" class="table table-striped boardgame_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">wishlist_priority</th>
|
||||
<th scope="col" class="no-sort">Thumbnail</th>
|
||||
<th scope="col">Naam</th>
|
||||
<th scope="col">Spelers</th>
|
||||
<th scope="col">Duratie</th>
|
||||
<th scope="col">Moeilijkheid</th>
|
||||
</tr>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="wishlist_table4" class="table table-striped boardgame_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">wishlist_priority</th>
|
||||
<th scope="col" class="no-sort">Thumbnail</th>
|
||||
<th scope="col">Naam</th>
|
||||
<th scope="col">Spelers</th>
|
||||
<th scope="col">Duratie</th>
|
||||
<th scope="col">Moeilijkheid</th>
|
||||
</tr>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
{% endblock body_block %}
|
||||
|
||||
|
||||
{% block extra_js_files %}
|
||||
|
||||
<script src="{{ url_for('static', filename='javascript/wishlist.js') }}" defer></script>
|
||||
|
||||
{% endblock extra_js_files %}
|
||||
Loading…
Reference in a new issue