Add games view

Work on displaying correct game information
Epic-er nav
This commit is contained in:
Michał Gdula 2023-05-17 23:04:17 +01:00
parent c1f8f67e64
commit 51ba6cd0ea
17 changed files with 182 additions and 51 deletions

5
DV8-Expo/.gitignore vendored
View file

@ -159,5 +159,10 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
# remove development files
/instance
/migrations
/storage
/logs
/website/static/.webpack-cache
/website/static/gen

View file

@ -5,17 +5,6 @@ from website.extensions import db
from flask_login import UserMixin
class Games(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
ageRating = db.Column(db.String, nullable=False)
description = db.Column(db.String, nullable=False)
thumbnail = db.Column(db.String, nullable=False)
background = db.Column(db.String, nullable=False)
downloadLink = db.Column(db.String, nullable=False)
approved = db.Column(db.Boolean, nullable=False, default=False)
class Images(db.Model):
id = db.Column(db.Integer, primary_key=True)
image = db.Column(db.String, nullable=False)
@ -38,6 +27,23 @@ class Authors(db.Model):
class Users(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
uuid = db.Column(db.String, nullable=False)
game_id = db.Column(db.Integer, db.ForeignKey("games.id"))
def get_id(self):
return int(self.id)
class Games(db.Model):
id = db.Column(db.Integer, primary_key=True)
approved = db.Column(db.Boolean, nullable=False, default=False)
visible = db.Column(db.Boolean, nullable=False, default=False)
name = db.Column(db.String, nullable=False)
description = db.Column(db.String, nullable=False)
thumbnail = db.Column(db.String, nullable=False)
background = db.Column(db.String, nullable=False)
downloadLink = db.Column(db.String)
ageRating = db.Column(db.String, nullable=False)
tags = db.relationship("Tags", backref="game", lazy=True)
owner_id = db.relationship("Users", backref="game", lazy=True)

View file

@ -1,9 +1,10 @@
from flask import Blueprint, render_template, redirect, flash
from flask_login import login_user, logout_user, login_required
from flask import Blueprint, render_template, redirect, flash, abort
from flask_login import login_user, logout_user, login_required, current_user
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired
from website.models import Users
from website.models import Users, Games
from website.extensions import db
blueprint = Blueprint("website", __name__)
@ -19,7 +20,25 @@ class LoginForm(FlaskForm):
@blueprint.route("/")
def index():
return render_template("index.html")
games = (Games.query
.filter_by(approved=True)
.filter_by(visible=True)
.all())
return render_template("index.html", games=games)
@blueprint.route("/g/<int:game_id>")
def g(game_id):
game = (Games.query
.filter_by(id=game_id)
.filter_by(approved=True)
.filter_by(visible=True)
.first())
if not game:
abort(404)
return render_template("game.html", game=game)
@blueprint.route("/login", methods=["GET", "POST"])
@ -35,6 +54,7 @@ def login():
return render_template("login.html", form=form)
@blueprint.route("/logout")
@login_required
def logout():

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

File diff suppressed because one or more lines are too long

View file

@ -1 +1,3 @@
window.onscroll=()=>{scrollFunction()};window.onload=()=>{scrollFunction()};function scrollFunction(){let nav=document.querySelector("nav");let scrollHeight=0;if(document.body.scrollTop>scrollHeight||document.documentElement.scrollTop>scrollHeight){nav.classList.add("scrolled");}else{nav.classList.remove("scrolled");}}
const defaultTitle="DV8 Game Expo <span>2023</span>";let prevTitle;window.onscroll=()=>{scrollFunction();checkSection();};window.onload=()=>{scrollFunction()};function scrollFunction(){let nav=document.querySelector("nav");let scrollHeight=0;if(document.body.scrollTop>scrollHeight||document.documentElement.scrollTop>scrollHeight){nav.classList.add("scrolled");}else{nav.classList.remove("scrolled");}}
function checkSection(){let navTitle=document.querySelector("nav > h1");let sections=document.querySelectorAll("section");if(window.pageYOffset<sections[0].offsetTop){if(prevTitle===defaultTitle)return;navTitle.innerHTML=defaultTitle;navTitle.style.animation="title-change 0.2s ease-in-out";prevTitle=defaultTitle;setTimeout(()=>{navTitle.style.animation="";},200);}
sections.forEach((section)=>{let top=section.offsetTop;let bottom=section.offsetTop+section.offsetHeight;if(window.pageYOffset>=top&&window.pageYOffset<bottom){if(prevTitle===section.id)return;navTitle.innerHTML=section.id;navTitle.style.animation="title-change 0.2s ease-in-out";prevTitle=section.id;setTimeout(()=>{navTitle.style.animation="";},200);}});}

View file

@ -1,4 +1,10 @@
window.onscroll = () => { scrollFunction() };
const defaultTitle = "DV8 Game Expo <span>2023</span>";
let prevTitle;
window.onscroll = () => {
scrollFunction();
checkSection();
};
window.onload = () => { scrollFunction() };
function scrollFunction() {
@ -13,3 +19,45 @@ function scrollFunction() {
nav.classList.remove("scrolled");
}
}
function checkSection() {
// Get the nav and sections
let navTitle = document.querySelector("nav > h1");
let sections = document.querySelectorAll("section");
// If we're at the top of the page, set the title to the default
if (window.pageYOffset < sections[0].offsetTop) {
// If we're already on the default title, don't do anything as it'll break the animation
if (prevTitle === defaultTitle) return;
navTitle.innerHTML = defaultTitle;
navTitle.style.animation = "title-change 0.2s ease-in-out";
prevTitle = defaultTitle;
// Remove the animation after it's done, so we can animate again
setTimeout(() => { navTitle.style.animation = ""; }, 200);
}
// While at this point we may not need to check for the sections
// There aren't many sections, so it's not a big deal
sections.forEach((section) => {
// Get the position of the section
let top = section.offsetTop;
let bottom = section.offsetTop + section.offsetHeight;
// If the section is on the screen is:
// 1. The top of the section is above the top of the screen
// 2. The bottom of the section is below the bottom of the screen
if (window.pageYOffset >= top && window.pageYOffset < bottom) {
// If we're already on the section, don't do anything as it'll break the animation
if (prevTitle === section.id) return;
navTitle.innerHTML = section.id;
navTitle.style.animation = "title-change 0.2s ease-in-out";
prevTitle = section.id;
// Remove the animation after it's done, so we can animate again
setTimeout(() => { navTitle.style.animation = ""; }, 200);
}
});
}

View file

@ -8,3 +8,11 @@
100%
opacity: 0
// text-shadow: 0 0 0 $primary
@keyframes title-change
0%
transform: translateX(-3rem)
opacity: 0
100%
transform: translateX(0)
opacity: 1

View file

@ -17,7 +17,6 @@ header
> span
font-family: $monospace-font
color: $accent
> p
margin: 0
font-size: 1.2rem

View file

@ -11,6 +11,11 @@ nav
top: 0
left: 0
font-weight: bold
font-family: $main-font
font-size: 1.1rem
white-space: nowrap
background: transparent
color: $primary
@ -20,12 +25,10 @@ nav
&::before
content: ""
position: absolute
top: -100%
left: 0
width: 100%
height: 100%
inset: 0
background: var(--nav)
transition: top 0.2s ease-in-out
transform: translateY(-100%)
transition: transform 0.2s ease-in-out
z-index: -1
> span
@ -33,23 +36,30 @@ nav
> a
margin: 0 0.75rem
font-size: 1.1rem
font-weight: bold
font-family: $main-font
padding: 0.1rem 0.5rem
text-decoration: none
color: inherit
transition: color 0.1s ease-in-out, font-weight 0.1s ease-in-out
transition: color 0.1s ease-in-out
&:hover
color: $accent
> h1
font-size: inherit
text-decoration: none
color: $secondary
opacity: 0
transition: opacity 0.1s ease-in-out
> span
font-family: $monospace-font
color: $accent
&.scrolled
color: $secondary
> a
font-weight: normal
> h1
opacity: 1
&::before
top: 0
transform: translateY(0)

View file

@ -21,6 +21,11 @@ section
justify-content: center
align-items: center
&.fill
background-color: $secondary
color: $primary
border-radius: $radius
div.games
margin: 1rem
display: grid

View file

@ -9,6 +9,12 @@ $radius: var(--radius)
$main-font: var(--main-font)
$monospace-font: var(--monospace-font)
// Accessibility setting
//*, *::before, *::after
// animation-duration: 0s !important
// transition: none !important
\:root
--primary: #332f2f
--secondary: #d7cec9

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View file

@ -7,6 +7,8 @@
<title>Game Event 23</title>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Rubik:ital,wght@0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800&display=swap">
@ -14,20 +16,18 @@
<script src="https://unpkg.com/@phosphor-icons/web"></script>
<!-- Stylesheets -->
{% assets "scripts" %}
<script src="{{ ASSET_URL }}" defer></script>
{% endassets %}
{% assets "scripts" %}<script src="{{ ASSET_URL }}" defer></script>{% endassets %}
<!-- Scripts -->
{% assets "styles" %}
<link rel="stylesheet" href="{{ ASSET_URL }}" type="text/css" defer>
{% endassets %}
{% assets "styles" %}<link rel="stylesheet" href="{{ ASSET_URL }}" type="text/css" defer>{% endassets %}
</head>
<body>
<nav>
<a href="{{ url_for('website.index') }}">Home</a>
<h1>DV8 Game Expo <span>2023</span></h1>
<span><!-- This is a separator --></span>
<a href="{{ url_for('website.index') }}">About</a>
<a href="{{ url_for('website.index') }}#">Home</a>
<a href="{{ url_for('website.index') }}#About">About</a>
<a href="{{ url_for('website.index') }}#Games">Games</a>
{% if current_user.is_authenticated %}<a href="{{ url_for('website.logout') }}">Logout</a>{% endif %}
</nav>

View file

@ -0,0 +1,18 @@
{% extends "base.html" %}
{% block background %}
{% if game.background %}
{{ url_for('static', filename='backgrounds/' + game.background) }}
{% else %}
{{ url_for('static', filename='backgrounds/default.jpg') }}
{% endif %}
{% endblock %}
{% block content %}
<header style="height: 40vh">
<h1>{{ game.name }}</h1>
</header>
<section class="fill">
<h2>Games</h2>
<p>Here are some games AAAA</p>
</section>
{% endblock %}

View file

@ -7,30 +7,34 @@
<i class="ph-bold ph-caret-double-down"></i>
</header>
<section>
<section id="About">
<h2>About</h2>
<p>Tap to add text</p>
</section>
<section>
<section id="Games">
<h2>Games</h2>
<p>Here are some games AAAA</p>
<div class="games">
{% for game in range(10) %}
{% for game in games %}
<div class="game-box">
<img src="{{ url_for('static', filename='images/3.jpg') }}" alt="game image">
<h2>game name</h2>
<p>mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow mow</p>
{% if game.thumbnail %}
<img src="{{ url_for('static', filename='thumbnails/' + game.thumbnail) }}" alt="game image">
{% else %}
<img src="{{ url_for('static', filename='thumbnails/default.jpg') }}" alt="game image">
{% endif %}
<h2>{{ game.name }}</h2>
<p>{{ game.description|truncate(100) }}</p>
<div class="options">
<a href="#" style="width: 100%">View</a>
<a href="#" style="width: 2.5rem"><i class="ph ph-download"></i></a>
<a href="{{ url_for('website.g', game_id=game.id) }}" style="width: 100%">View</a>
{% if game.downloadLink %}<a href="{{ game.downloadLink }}" style="background-color: var(--secondary-button); width: 2.5rem"><i class="ph ph-download"></i></a>{% endif %}
<a href="#" style="background-color: var(--secondary-button); width: 2.5rem"><i class="ph ph-warning"></i></a>
</div>
</div>
{% endfor %}
</div>
</section>
{% endblock %}