This commit is contained in:
William Bell committed 2026-03-05 12:22:09 +00:00
commit 62f557f9c2
33 files changed
+121 -166

No files matched your search

+1
View File
@@ -218,3 +218,4 @@ database/species.db
static/images/.DS_Store
.DS_Store
database/database.db
+1 -1
View File
@@ -1,4 +1,4 @@
[homepage]
[featured_species]
species1 = Sumatran Tiger
species2 = Javan Rhinoceros
species3 = Bali Myna
-49
View File
@@ -1,49 +0,0 @@
import sqlite3
from datetime import datetime
database = sqlite3.connect("database/species.db", check_same_thread=False)
database.execute(
"""
CREATE TABLE IF NOT EXISTS species (
species_id INTEGER PRIMARY KEY AUTOINCREMENT,
species_english TEXT,
species_latin TEXT,
body_text TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
"""
)
database.commit()
print("Database initialized.")
def add_species(english, latin, body):
cursor = database.cursor()
cursor.execute(
"""
INSERT INTO species (
species_english,
species_latin,
body_text,
created_at
)
VALUES (?, ?, ?, ?)
""",
(english, latin, body, datetime.now()),
)
cursor.close()
database.commit()
print("Species added successfully.")
# Example usage
if __name__ == "__main__":
english_name = input("Species english name: ").lower()
latin_name = input("Species latin name: ").lower()
main_text = input("Species information: ").lower()
add_species(english_name, latin_name, main_text)
+7 -5
View File
@@ -2,7 +2,7 @@ from datetime import datetime
from database.db_connection import get_db
def add_species(english, latin, body, category, extinction_risk):
def add_species(english, latin, body, category, extinction_risk, image_id):
with get_db() as conn:
conn.execute("""
INSERT INTO species (
@@ -11,10 +11,12 @@ def add_species(english, latin, body, category, extinction_risk):
body_text,
category,
extinction_risk,
created_at
created_at,
photoid
)
VALUES (?, ?, ?, ?, ?, ?)
""", (english, latin.lower(), body, category, extinction_risk, datetime.now()))
VALUES (?, ?, ?, ?, ?, ?, ?)
""", (english, latin.lower(), body, category, extinction_risk, datetime.now(), image_id))
def get_all_species():
@@ -43,7 +45,7 @@ WHERE
OR instr(LOWER(COALESCE(CAST(category AS TEXT), '')), ?1) > 0
OR instr(LOWER(COALESCE(CAST(extinction_risk AS TEXT), '')), ?1) > 0;""",
(query.lower(),)
).fetchmany()
).fetchall()
return [dict(row) for row in rows]
+1 -1
View File
@@ -1,7 +1,7 @@
import sqlite3
from contextlib import contextmanager
DATABASE_PATH = "database/species.db"
DATABASE_PATH = "database/database.db"
@contextmanager
def get_db():
+8 -1
View File
@@ -15,6 +15,7 @@ SEED_SPECIES = [
),
"category": "Mammal",
"extinction_risk": "Critically Endangered",
"photoid": "sumatran tiger",
},
{
"species_english": "Javan Rhinoceros",
@@ -28,6 +29,7 @@ SEED_SPECIES = [
),
"category": "Mammal",
"extinction_risk": "Critically Endangered",
"photoid": "javan rhinoceros",
},
{
"species_english": "Bali Myna",
@@ -41,6 +43,7 @@ SEED_SPECIES = [
),
"category": "Bird",
"extinction_risk": "Critically Endangered",
"photoid": "bali myna"
},
{
"species_english": "Javan Eagle",
@@ -55,6 +58,7 @@ SEED_SPECIES = [
),
"category": "Bird",
"extinction_risk": "Endangered",
"photoid": "javan eagle"
},
{
"species_english": "Tarsius",
@@ -69,6 +73,7 @@ SEED_SPECIES = [
),
"category": "Mammal",
"extinction_risk": "Endangered",
"photoid": "tarsius"
},
{
"species_english": "Celebes Crested Macaque",
@@ -82,6 +87,7 @@ SEED_SPECIES = [
),
"category": "Mammal",
"extinction_risk": "Critically Endangered",
"photoid": "celebes crested macaque"
},
]
@@ -96,7 +102,8 @@ def init_database():
body_text TEXT,
category TEXT,
extinction_risk TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
photoid TEXT
)
""")
print("Database initialised.")
Binary file not shown.
+7
View File
@@ -0,0 +1,7 @@
from flask import render_template, Blueprint, request, redirect, url_for
page = Blueprint("login", __name__, url_prefix="")
@page.route("/login")
def portal():
return render_template("accounts/login.jinja")
+2 -5
View File
@@ -1,16 +1,13 @@
from flask import render_template, Blueprint
import configparser
config = configparser.ConfigParser()
from utilities.featured_species import featured_species_function
page = Blueprint("home", __name__, url_prefix="/")
@page.route("/")
def home():
config.read('config.ini')
featured_species = list(dict(config["homepage"]).values())
# print(f'Featured species: {species1}, {species2}, {species3}')
featured_species = featured_species_function('config.ini')
return render_template(
"home/home.jinja",
featured_species=featured_species
+7 -6
View File
@@ -1,17 +1,17 @@
from flask import render_template, Blueprint, request
import configparser
from database.db_commands import get_all_species, search_species
from database.db_commands import get_all_species, search_species, get_species_by_name
from utilities.featured_species import featured_species_function
config = configparser.ConfigParser()
page = Blueprint("species", __name__, url_prefix="/species")
# species database page
@page.route("")
def all_species():
config.read('config.ini')
featured_species = list(dict(config["homepage"]).values())
def all_species():
featured_species = featured_species_function('config.ini')
species_list = get_all_species()
@@ -26,10 +26,11 @@ def all_species():
featured_species=featured_species
)
# search page
@page.route("/search")
def search():
query = request.args.get("search-query")
results = search_species(query)
print(results)
return render_template("/species/species_search.jinja", results=results, query=query)
+1
View File
@@ -28,6 +28,7 @@ def data(species_english):
main_text =database_entry["body_text"],
category =database_entry["category"].capitalize(),
extinction_risk =database_entry["extinction_risk"],
photoid =database_entry["photoid"]
)
except TypeError as error_information:
return render_template(
+5 -2
View File
@@ -1,6 +1,7 @@
from flask import render_template, Blueprint, request, redirect, url_for
from database.db_commands import add_species, delete_species, get_species_by_name
import os
import uuid
page = Blueprint("species_portal", __name__, url_prefix="/species/portal")
@@ -19,10 +20,12 @@ def add_species_to_database():
category = request.form["category"].capitalize()
extinction_risk = request.form["extinction_risk"]
species_image = request.files["species_image"]
image_id = ""
if species_image:
species_image.save(f"static/images/species_database/{eng_name}.jpg")
image_id = str(uuid.uuid4())
species_image.save(f"static/images/species_database/{image_id}.jpg")
print(category, extinction_risk)
add_species(eng_name, latin_name, main_text, category, extinction_risk)
add_species(eng_name, latin_name, main_text, category, extinction_risk, image_id)
return render_template(
"species_portal/species_portal_success.jinja",
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Whitespace-only changes.
+3 -3
View File
@@ -547,7 +547,7 @@ input:focus {
position: absolute;
top: 100%;
left: 0;
background-color: white;
background-color: rgb(0, 0, 0);
min-width: 160px;
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
z-index: 3;
@@ -558,7 +558,7 @@ input:focus {
display: block;
padding: 10px 15px;
text-decoration: none;
color: rgb(255, 255, 255);
color: rgb(35, 35, 35);
z-index: 999;
}
@@ -580,7 +580,7 @@ input:focus {
/* Hover effects */
.dropdown-content a:hover {
background-color: #f1f1f1;
background-color: #555555;
}
/* Show dropdown on hover */
+23
View File
@@ -0,0 +1,23 @@
{# needs to redirect if user logged in #}
{% extends "base.jinja" %}
{% block title %} Species Upload Portal {% endblock %}
{% block head %}
{% endblock %}
{% block content %}
{% from 'button.jinja' import button %}
<section id="hero" class="form">
<form action="" class="container" method="POST">
<div class="form-group">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required>
</div>
<div class="form-group">
<label for="password">Password:</label>
<input type="password" id="password" name="password">
</div>
<button type="submit" class="submit-button">
Login
</button>
</form>
</section>
{% endblock %}
+18
View File
@@ -0,0 +1,18 @@
{% macro display_all_items(items)%}
{# Displays all species in the provided 'items' array #}
{# Used in the species database and species results pages #}
<section class="species-grid">
{% for item in items %}
<a href="/species/{{ item['species_english'] }}" class="container-lite">
<h3 class="plain-white-text">{{ item['species_english'] }}</h3>
<div
style="background-image: url('{{ url_for('static', filename='images/species_database/' ~ item['photoid'] ~ '.jpg') }}');" class="div-image">
</div>
<p style="color: var(--text)">
Main category: {{ item['category'] }}
</p>
</a>
{% endfor %}
</section>
{% endmacro %}
+3 -3
View File
@@ -9,9 +9,9 @@
<div
style="display: flex; flex-wrap: wrap; gap: 20px; margin-top: 30px; text-decoration: none; justify-content: space-evenly">
{%for species in featured_species%}
<a href="/species/{{species}}" class="container-lite">
<h3 class="plain-white-text">{{species}}</h3>
<div style="background-image: url('images/species_database/{{species}}.jpg');" class="div-image">
<a href="/species/{{ species['species_english'] }}" class="container-lite">
<h3 class="plain-white-text">{{ species['species_english'] }}</h3>
<div style="background-image: url('images/species_database/{{ species['photoid'] }}.jpg');" class="div-image">
</div>
</a>
+1
View File
@@ -15,6 +15,7 @@
<a href="/species/portal">Add Species</a>
<a href="/species">View Species</a>
<a href="/species_search">Search Species</a>
<a href="/login">Login page</a>
</div>
</div>
{# todo #}
+9
View File
@@ -0,0 +1,9 @@
{% macro search_bar(destination)%}
{# input the url of the page containing the backend for the search #}
{# e.g. for the species search: "/species/search" #}
{# used in species.jinja #}
<form action="{{destination}}" method="GET" class="search">
<input type="text" name="search-query" placeholder="Search all species..." class="bar">
<input type="submit" value="Search" class="button">
</form>
{% endmacro %}
+5 -21
View File
@@ -4,7 +4,9 @@
{% endblock %}
{% block content %}
{% from 'button.jinja' import button %}
{% from 'featured_species.jinja' import featured_species_section%}
{% from 'featured_species.jinja' import featured_species_section %}
{% from 'display_items.jinja' import display_all_items %}
{% from 'search_bar.jinja' import search_bar%}
<section class="title">
Species Database
</section>
@@ -12,25 +14,7 @@ Species Database
{# If you want to change the featured species please do so in config.ini - CS #}
{{featured_species_section(featured_species, False)}}
{# All Species #}
<div>
<form action="/species/search" method="GET" class="search">
<input type="text" name="search-query" placeholder="Search all species..." class="bar">
<input type="submit" value="Search" class="button">
</form>
</div>
{{search_bar("/species/search")}}
<h2 style="text-align: center; margin-top: 30px;">All Species</h2>
<section class="species-grid">
{% for sp in species %}
<a href="/species/{{ sp['species_english'] }}" class="container-lite">
<h3 class="plain-white-text">{{ sp['species_english'] }}</h3>
<div
style="background-image: url('{{ url_for('static', filename='images/species_database/' ~ sp['species_english'] ~ '.jpg') }}');" class="div-image">
</div>
<p style="color: var(--text)">
Main category: {{ sp['category'] }}
</p>
</a>
{% endfor %}
</section>
{{display_all_items(species)}}
{% endblock %}
+4 -22
View File
@@ -4,30 +4,12 @@
{% endblock %}
{% block content %}
{% from 'button.jinja' import button %}
{% from 'featured_species.jinja' import featured_species_section%}
{% from 'display_items.jinja' import display_all_items %}
{% from 'search_bar.jinja' import search_bar%}
<section class="title">
Species Database
</section>
{# All Species #}
<div>
<form action="/species/search" method="GET" class="search">
<input type="text" name="search-query" placeholder="Search all species..." value="{{query}}" class="bar">
<input type="submit" value="Search" class="button">
</form>
</div>
<h2 style="text-align: center; margin-top: 30px;">All Species</h2>
<section class="species-grid">
{% for sp in results %}
<a href="/species/{{ sp['species_english'] }}" class="container-lite">
<h3 class="plain-white-text">{{ sp['species_english'] }}</h3>
<div
style="background-image: url('{{ url_for('static', filename='images/species_database/' ~ sp['species_english'] ~ '.jpg') }}');" class="div-image">
</div>
<p style="color: var(--text)">
Main category: {{ sp['category'] }}
</p>
</a>
{% endfor %}
</section>
{{search_bar("/species/search")}}
{{display_all_items(results)}}
{% endblock %}
@@ -9,7 +9,7 @@
<h1>{{ english_name }}</h1>
<h2><em>{{ latin_name }}</em></h2>
<p>Category: {{category}}</p>
<img src="/images/species_database/{{ english_name }}.jpg" class="species-photo" style="max-width: 100%; height: auto; border-radius: inherit;">
<img src="/images/species_database/{{ photoid }}.jpg" class="species-photo" style="max-width: 100%; height: auto; border-radius: inherit;">
<p>{{ main_text }}</p>
<p>This species is currently classed as: {{extinction_risk}}</p>
{% if extinction_risk == "Not Evaluated" %}
-46
View File
@@ -1,46 +0,0 @@
import sqlite3
from datetime import datetime
# from main import database as db
def add_species(english, latin, body):
db = sqlite3.connect("database/species.db", check_same_thread=False)
db.execute(
"""
CREATE TABLE IF NOT EXISTS species (
species_id INTEGER PRIMARY KEY AUTOINCREMENT,
species_english TEXT,
species_latin TEXT,
body_text TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
"""
)
db.commit()
print("Database initialized.")
cursor = db.cursor()
cursor.execute(
"""
INSERT INTO species (
species_english,
species_latin,
body_text,
created_at
)
VALUES (?, ?, ?, ?)
""",
(english, latin, body, datetime.now()),
)
db.commit()
db.close()
print("Species added successfully.")
+14
View File
@@ -0,0 +1,14 @@
import configparser
from database.db_commands import get_species_by_name
def featured_species_function(config_file):
config = configparser.ConfigParser()
config.read(config_file)
featured_species_list = list(dict(config["featured_species"]).values())
featured_species = []
for species in featured_species_list:
featured_species.append(get_species_by_name(species))
return featured_species