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. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
# remove development files # remove development files
/instance
/migrations
/storage /storage
/logs /logs
/website/static/.webpack-cache
/website/static/gen

View file

@ -5,17 +5,6 @@ from website.extensions import db
from flask_login import UserMixin 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): class Images(db.Model):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
image = db.Column(db.String, nullable=False) image = db.Column(db.String, nullable=False)
@ -38,6 +27,23 @@ class Authors(db.Model):
class Users(db.Model, UserMixin): class Users(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
uuid = db.Column(db.String, nullable=False) uuid = db.Column(db.String, nullable=False)
game_id = db.Column(db.Integer, db.ForeignKey("games.id"))
def get_id(self): def get_id(self):
return int(self.id) 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 import Blueprint, render_template, redirect, flash, abort
from flask_login import login_user, logout_user, login_required from flask_login import login_user, logout_user, login_required, current_user
from flask_wtf import FlaskForm from flask_wtf import FlaskForm
from wtforms import StringField from wtforms import StringField
from wtforms.validators import DataRequired 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__) blueprint = Blueprint("website", __name__)
@ -19,7 +20,25 @@ class LoginForm(FlaskForm):
@blueprint.route("/") @blueprint.route("/")
def index(): 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"]) @blueprint.route("/login", methods=["GET", "POST"])
@ -35,6 +54,7 @@ def login():
return render_template("login.html", form=form) return render_template("login.html", form=form)
@blueprint.route("/logout") @blueprint.route("/logout")
@login_required @login_required
def logout(): 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() }; window.onload = () => { scrollFunction() };
function scrollFunction() { function scrollFunction() {
@ -13,3 +19,45 @@ function scrollFunction() {
nav.classList.remove("scrolled"); 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% 100%
opacity: 0 opacity: 0
// text-shadow: 0 0 0 $primary // 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 > span
font-family: $monospace-font font-family: $monospace-font
color: $accent color: $accent
> p > p
margin: 0 margin: 0
font-size: 1.2rem font-size: 1.2rem

View file

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

View file

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

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View file

@ -7,6 +7,8 @@
<title>Game Event 23</title> <title>Game Event 23</title>
<!-- Google Fonts --> <!-- 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=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"> <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> <script src="https://unpkg.com/@phosphor-icons/web"></script>
<!-- Stylesheets --> <!-- Stylesheets -->
{% assets "scripts" %} {% assets "scripts" %}<script src="{{ ASSET_URL }}" defer></script>{% endassets %}
<script src="{{ ASSET_URL }}" defer></script>
{% endassets %}
<!-- Scripts --> <!-- Scripts -->
{% assets "styles" %} {% assets "styles" %}<link rel="stylesheet" href="{{ ASSET_URL }}" type="text/css" defer>{% endassets %}
<link rel="stylesheet" href="{{ ASSET_URL }}" type="text/css" defer>
{% endassets %}
</head> </head>
<body> <body>
<nav> <nav>
<a href="{{ url_for('website.index') }}">Home</a> <h1>DV8 Game Expo <span>2023</span></h1>
<span><!-- This is a separator --></span> <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 %} {% if current_user.is_authenticated %}<a href="{{ url_for('website.logout') }}">Logout</a>{% endif %}
</nav> </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> <i class="ph-bold ph-caret-double-down"></i>
</header> </header>
<section> <section id="About">
<h2>About</h2> <h2>About</h2>
<p>Tap to add text</p> <p>Tap to add text</p>
</section> </section>
<section> <section id="Games">
<h2>Games</h2> <h2>Games</h2>
<p>Here are some games AAAA</p> <p>Here are some games AAAA</p>
<div class="games"> <div class="games">
{% for game in range(10) %} {% for game in games %}
<div class="game-box"> <div class="game-box">
<img src="{{ url_for('static', filename='images/3.jpg') }}" alt="game image"> {% if game.thumbnail %}
<h2>game name</h2> <img src="{{ url_for('static', filename='thumbnails/' + game.thumbnail) }}" alt="game image">
<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> {% 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"> <div class="options">
<a href="#" style="width: 100%">View</a> <a href="{{ url_for('website.g', game_id=game.id) }}" style="width: 100%">View</a>
<a href="#" style="width: 2.5rem"><i class="ph ph-download"></i></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> <a href="#" style="background-color: var(--secondary-button); width: 2.5rem"><i class="ph ph-warning"></i></a>
</div> </div>
</div> </div>
{% endfor %} {% endfor %}
</div> </div>
</section> </section>
{% endblock %} {% endblock %}