From 1b36a283d53388d7932a207f87fa7492cc9c55dd Mon Sep 17 00:00:00 2001 From: Jonny Ervine Date: Mon, 29 Sep 2025 20:25:10 +0800 Subject: [PATCH] Add datbase setup --- motm_app/db_setup.py | 288 ++++++++++++++++++++++++ motm_app/forms.py | 36 +++ motm_app/main.py | 126 ++++++++++- motm_app/templates/database_setup.html | 260 +++++++++++++++++++++ motm_app/templates/database_status.html | 162 +++++++++++++ motm_app/templates/index.html | 8 + 6 files changed, 879 insertions(+), 1 deletion(-) create mode 100644 motm_app/db_setup.py create mode 100644 motm_app/templates/database_setup.html create mode 100644 motm_app/templates/database_status.html diff --git a/motm_app/db_setup.py b/motm_app/db_setup.py new file mode 100644 index 0000000..c450c35 --- /dev/null +++ b/motm_app/db_setup.py @@ -0,0 +1,288 @@ +# encoding=utf-8 +""" +Database setup and configuration management module. +Handles database initialization, configuration saving/loading, and sample data creation. +""" + +import os +import json +import configparser +from datetime import datetime +from sqlalchemy import create_engine, text +from sqlalchemy.exc import SQLAlchemyError +from database import Base, db_config, init_database +from database import ( + Player, Club, Team, MatchSquad, HockeyFixture, + AdminSettings, MotmVote, MatchComment, HockeyUser +) + +class DatabaseConfigManager: + """Manages database configuration and setup.""" + + def __init__(self, config_file='database_config.ini'): + self.config_file = config_file + self.config = configparser.ConfigParser() + self.load_config() + + def load_config(self): + """Load configuration from file.""" + if os.path.exists(self.config_file): + self.config.read(self.config_file) + else: + # Create default configuration + self.config['DATABASE'] = { + 'type': 'sqlite', + 'sqlite_database_path': 'hockey_results.db' + } + self.config['MYSQL'] = { + 'host': 'localhost', + 'port': '3306', + 'database': 'hockey_results', + 'username': 'root', + 'password': '', + 'charset': 'utf8mb4' + } + self.config['POSTGRESQL'] = { + 'host': 'localhost', + 'port': '5432', + 'database': 'hockey_results', + 'username': 'postgres', + 'password': '' + } + + def save_config(self, form_data): + """Save configuration from form data.""" + # Update database type + self.config['DATABASE']['type'] = form_data['database_type'] + + # Update SQLite settings + if 'sqlite_database_path' in form_data: + self.config['DATABASE']['sqlite_database_path'] = form_data['sqlite_database_path'] + + # Update MySQL settings + if 'mysql_host' in form_data: + self.config['MYSQL']['host'] = form_data['mysql_host'] + if 'mysql_port' in form_data: + self.config['MYSQL']['port'] = str(form_data['mysql_port']) + if 'mysql_database' in form_data: + self.config['MYSQL']['database'] = form_data['mysql_database'] + if 'mysql_username' in form_data: + self.config['MYSQL']['username'] = form_data['mysql_username'] + if 'mysql_password' in form_data: + self.config['MYSQL']['password'] = form_data['mysql_password'] + if 'mysql_charset' in form_data: + self.config['MYSQL']['charset'] = form_data['mysql_charset'] + + # Update PostgreSQL settings + if 'postgres_host' in form_data: + self.config['POSTGRESQL']['host'] = form_data['postgres_host'] + if 'postgres_port' in form_data: + self.config['POSTGRESQL']['port'] = str(form_data['postgres_port']) + if 'postgres_database' in form_data: + self.config['POSTGRESQL']['database'] = form_data['postgres_database'] + if 'postgres_username' in form_data: + self.config['POSTGRESQL']['username'] = form_data['postgres_username'] + if 'postgres_password' in form_data: + self.config['POSTGRESQL']['password'] = form_data['postgres_password'] + + # Save to file + with open(self.config_file, 'w') as f: + self.config.write(f) + + # Update environment variables + self._update_environment_variables() + + def _update_environment_variables(self): + """Update environment variables based on configuration.""" + db_type = self.config['DATABASE']['type'] + + if db_type == 'sqlite': + os.environ['DATABASE_TYPE'] = 'sqlite' + os.environ['SQLITE_DATABASE_PATH'] = self.config['DATABASE']['sqlite_database_path'] + + elif db_type == 'mysql': + os.environ['DATABASE_TYPE'] = 'mysql' + os.environ['MYSQL_HOST'] = self.config['MYSQL']['host'] + os.environ['MYSQL_PORT'] = self.config['MYSQL']['port'] + os.environ['MYSQL_DATABASE'] = self.config['MYSQL']['database'] + os.environ['MYSQL_USER'] = self.config['MYSQL']['username'] + os.environ['MYSQL_PASSWORD'] = self.config['MYSQL']['password'] + os.environ['MYSQL_CHARSET'] = self.config['MYSQL']['charset'] + + elif db_type == 'postgresql': + os.environ['DATABASE_TYPE'] = 'postgresql' + os.environ['POSTGRES_HOST'] = self.config['POSTGRESQL']['host'] + os.environ['POSTGRES_PORT'] = self.config['POSTGRESQL']['port'] + os.environ['POSTGRES_DATABASE'] = self.config['POSTGRESQL']['database'] + os.environ['POSTGRES_USER'] = self.config['POSTGRESQL']['username'] + os.environ['POSTGRES_PASSWORD'] = self.config['POSTGRESQL']['password'] + + def test_connection(self, form_data): + """Test database connection with provided settings.""" + try: + # Temporarily update environment variables + old_env = {} + for key in ['DATABASE_TYPE', 'SQLITE_DATABASE_PATH', 'MYSQL_HOST', 'MYSQL_PORT', + 'MYSQL_DATABASE', 'MYSQL_USER', 'MYSQL_PASSWORD', 'MYSQL_CHARSET', + 'POSTGRES_HOST', 'POSTGRES_PORT', 'POSTGRES_DATABASE', 'POSTGRES_USER', 'POSTGRES_PASSWORD']: + old_env[key] = os.environ.get(key) + + # Set new environment variables + os.environ['DATABASE_TYPE'] = form_data['database_type'] + + if form_data['database_type'] == 'sqlite': + os.environ['SQLITE_DATABASE_PATH'] = form_data['sqlite_database_path'] + elif form_data['database_type'] == 'mysql': + os.environ['MYSQL_HOST'] = form_data['mysql_host'] + os.environ['MYSQL_PORT'] = str(form_data['mysql_port']) + os.environ['MYSQL_DATABASE'] = form_data['mysql_database'] + os.environ['MYSQL_USER'] = form_data['mysql_username'] + os.environ['MYSQL_PASSWORD'] = form_data['mysql_password'] + os.environ['MYSQL_CHARSET'] = form_data['mysql_charset'] + elif form_data['database_type'] == 'postgresql': + os.environ['POSTGRES_HOST'] = form_data['postgres_host'] + os.environ['POSTGRES_PORT'] = str(form_data['postgres_port']) + os.environ['POSTGRES_DATABASE'] = form_data['postgres_database'] + os.environ['POSTGRES_USER'] = form_data['postgres_username'] + os.environ['POSTGRES_PASSWORD'] = form_data['postgres_password'] + + # Test connection + from database import DatabaseConfig + test_config = DatabaseConfig() + engine = test_config.engine + + with engine.connect() as conn: + result = conn.execute(text("SELECT 1")) + result.fetchone() + + return True, "Connection successful!" + + except Exception as e: + return False, f"Connection failed: {str(e)}" + + finally: + # Restore original environment variables + for key, value in old_env.items(): + if value is None: + os.environ.pop(key, None) + else: + os.environ[key] = value + + def initialize_database(self, create_sample_data=True): + """Initialize database with tables and optionally sample data.""" + try: + # Create tables + init_database() + + if create_sample_data: + self._create_sample_data() + + return True, "Database initialized successfully!" + + except Exception as e: + return False, f"Database initialization failed: {str(e)}" + + def _create_sample_data(self): + """Create sample data for testing.""" + from database import get_db_session + + session = get_db_session() + try: + # Create sample clubs + clubs_data = [ + {'hockey_club': 'HKFC', 'logo_url': '/static/images/hkfc_logo.png'}, + {'hockey_club': 'KCC', 'logo_url': '/static/images/kcc_logo.png'}, + {'hockey_club': 'USRC', 'logo_url': '/static/images/usrc_logo.png'}, + {'hockey_club': 'Valley', 'logo_url': '/static/images/valley_logo.png'}, + ] + + for club_data in clubs_data: + club = Club(**club_data) + session.add(club) + + # Create sample teams + teams_data = [ + {'club': 'HKFC', 'team': 'A', 'display_name': 'HKFC A', 'league': 'Premier Division'}, + {'club': 'HKFC', 'team': 'B', 'display_name': 'HKFC B', 'league': 'Division 1'}, + {'club': 'HKFC', 'team': 'C', 'display_name': 'HKFC C', 'league': 'Division 2'}, + {'club': 'HKFC', 'team': 'D', 'display_name': 'HKFC D', 'league': 'Division 3'}, + ] + + for team_data in teams_data: + team = Team(**team_data) + session.add(team) + + # Create sample players + players_data = [ + {'player_number': 1, 'player_forenames': 'John', 'player_surname': 'Smith', 'player_nickname': 'Smithers', 'player_team': 'HKFC D'}, + {'player_number': 2, 'player_forenames': 'Mike', 'player_surname': 'Jones', 'player_nickname': 'Jonesy', 'player_team': 'HKFC D'}, + {'player_number': 3, 'player_forenames': 'David', 'player_surname': 'Brown', 'player_nickname': 'Brownie', 'player_team': 'HKFC D'}, + {'player_number': 4, 'player_forenames': 'Chris', 'player_surname': 'Wilson', 'player_nickname': 'Willy', 'player_team': 'HKFC D'}, + {'player_number': 5, 'player_forenames': 'Tom', 'player_surname': 'Taylor', 'player_nickname': 'Tayls', 'player_team': 'HKFC D'}, + ] + + for player_data in players_data: + player = Player(**player_data) + session.add(player) + + # Create sample admin settings + admin_settings = AdminSettings( + userid='admin', + next_fixture=1, + next_club='KCC', + next_team='KCC A', + curr_motm=1, + curr_dotd=2, + oppo_logo='/static/images/kcc_logo.png', + hkfc_logo='/static/images/hkfc_logo.png', + motm_url_suffix='abc123', + prev_fixture=0 + ) + session.add(admin_settings) + + # Create sample fixtures + fixtures_data = [ + {'fixture_number': 1, 'date': datetime(2024, 1, 15), 'home_team': 'HKFC D', 'away_team': 'KCC A', 'venue': 'HKFC'}, + {'fixture_number': 2, 'date': datetime(2024, 1, 22), 'home_team': 'USRC A', 'away_team': 'HKFC D', 'venue': 'USRC'}, + {'fixture_number': 3, 'date': datetime(2024, 1, 29), 'home_team': 'HKFC D', 'away_team': 'Valley A', 'venue': 'HKFC'}, + ] + + for fixture_data in fixtures_data: + fixture = HockeyFixture(**fixture_data) + session.add(fixture) + + session.commit() + + except Exception as e: + session.rollback() + raise e + finally: + session.close() + + def get_config_dict(self): + """Get configuration as dictionary for form population.""" + config_dict = {} + + # Database type + config_dict['database_type'] = self.config['DATABASE'].get('type', 'sqlite') + config_dict['sqlite_database_path'] = self.config['DATABASE'].get('sqlite_database_path', 'hockey_results.db') + + # MySQL settings + config_dict['mysql_host'] = self.config['MYSQL'].get('host', 'localhost') + config_dict['mysql_port'] = int(self.config['MYSQL'].get('port', '3306')) + config_dict['mysql_database'] = self.config['MYSQL'].get('database', 'hockey_results') + config_dict['mysql_username'] = self.config['MYSQL'].get('username', 'root') + config_dict['mysql_password'] = self.config['MYSQL'].get('password', '') + config_dict['mysql_charset'] = self.config['MYSQL'].get('charset', 'utf8mb4') + + # PostgreSQL settings + config_dict['postgres_host'] = self.config['POSTGRESQL'].get('host', 'localhost') + config_dict['postgres_port'] = int(self.config['POSTGRESQL'].get('port', '5432')) + config_dict['postgres_database'] = self.config['POSTGRESQL'].get('database', 'hockey_results') + config_dict['postgres_username'] = self.config['POSTGRESQL'].get('username', 'postgres') + config_dict['postgres_password'] = self.config['POSTGRESQL'].get('password', '') + + return config_dict + +# Global instance +db_config_manager = DatabaseConfigManager() diff --git a/motm_app/forms.py b/motm_app/forms.py index 863312d..b60b1e4 100644 --- a/motm_app/forms.py +++ b/motm_app/forms.py @@ -37,3 +37,39 @@ class goalsAssistsForm(FlaskForm): assists = SelectField('Assists:', choices=[(0, '0'), (1, '1'), (2, '2'), (3, '3'), (4, '4')]) goals = SelectField('Goals:', choices=[(0, '0'), (1, '1'), (2, '2'), (3, '3'), (4, '4')]) submit = SubmitField('Submit') + + +class DatabaseSetupForm(FlaskForm): + """Form for database setup and configuration.""" + database_type = SelectField('Database Type', + choices=[('sqlite', 'SQLite'), ('mysql', 'MySQL/MariaDB'), ('postgresql', 'PostgreSQL')], + validators=[InputRequired()]) + + # SQLite fields + sqlite_database_path = StringField('Database File Path', + default='hockey_results.db', + validators=[InputRequired()]) + + # MySQL/MariaDB fields + mysql_host = StringField('Host', default='localhost') + mysql_port = IntegerField('Port', default=3306) + mysql_database = StringField('Database Name', default='hockey_results') + mysql_username = StringField('Username', default='root') + mysql_password = PasswordField('Password') + mysql_charset = StringField('Charset', default='utf8mb4') + + # PostgreSQL fields + postgres_host = StringField('Host', default='localhost') + postgres_port = IntegerField('Port', default=5432) + postgres_database = StringField('Database Name', default='hockey_results') + postgres_username = StringField('Username', default='postgres') + postgres_password = PasswordField('Password') + + # Setup options + create_sample_data = BooleanField('Create Sample Data', default=True) + initialize_tables = BooleanField('Initialize Database Tables', default=True) + + # Action buttons + test_connection = SubmitField('Test Connection') + save_config = SubmitField('Save Configuration') + initialize_database = SubmitField('Initialize Database') diff --git a/motm_app/main.py b/motm_app/main.py index ae6cd25..d68f6b4 100644 --- a/motm_app/main.py +++ b/motm_app/main.py @@ -8,16 +8,18 @@ from datetime import datetime from app import app, randomUrlSuffix from flask import Flask, flash, render_template, request, redirect, url_for, jsonify +from sqlalchemy import text from flask_wtf import FlaskForm from flask_bootstrap import Bootstrap from flask_basicauth import BasicAuth from wtforms import StringField, PasswordField, BooleanField from wtforms import DateField from wtforms.validators import InputRequired, Email, Length -from forms import motmForm, adminSettingsForm2, goalsAssistsForm +from forms import motmForm, adminSettingsForm2, goalsAssistsForm, DatabaseSetupForm from db_config import sql_write, sql_write_static, sql_read, sql_read_static from tables import matchSquadTable from readSettings import mySettings +from db_setup import db_config_manager app.config['BASIC_AUTH_USERNAME'] = 'admin' app.config['BASIC_AUTH_PASSWORD'] = 'letmein' @@ -372,5 +374,127 @@ def poty_chart(): return render_template('poty_chart.html') +# ==================== DATABASE SETUP SECTION ==================== + +@app.route('/admin/database-setup', methods=['GET', 'POST']) +@basic_auth.required +def database_setup(): + """Admin page for database setup and configuration""" + form = DatabaseSetupForm() + + # Load current configuration + current_config = db_config_manager.get_config_dict() + + # Populate form with current configuration + for field_name, value in current_config.items(): + if hasattr(form, field_name): + getattr(form, field_name).data = value + + if request.method == 'POST': + if form.test_connection.data: + # Test database connection + form_data = { + 'database_type': form.database_type.data, + 'sqlite_database_path': form.sqlite_database_path.data, + 'mysql_host': form.mysql_host.data, + 'mysql_port': form.mysql_port.data, + 'mysql_database': form.mysql_database.data, + 'mysql_username': form.mysql_username.data, + 'mysql_password': form.mysql_password.data, + 'mysql_charset': form.mysql_charset.data, + 'postgres_host': form.postgres_host.data, + 'postgres_port': form.postgres_port.data, + 'postgres_database': form.postgres_database.data, + 'postgres_username': form.postgres_username.data, + 'postgres_password': form.postgres_password.data, + } + + success, message = db_config_manager.test_connection(form_data) + if success: + flash(f'✅ {message}', 'success') + else: + flash(f'❌ {message}', 'error') + + elif form.save_config.data: + # Save configuration + form_data = { + 'database_type': form.database_type.data, + 'sqlite_database_path': form.sqlite_database_path.data, + 'mysql_host': form.mysql_host.data, + 'mysql_port': form.mysql_port.data, + 'mysql_database': form.mysql_database.data, + 'mysql_username': form.mysql_username.data, + 'mysql_password': form.mysql_password.data, + 'mysql_charset': form.mysql_charset.data, + 'postgres_host': form.postgres_host.data, + 'postgres_port': form.postgres_port.data, + 'postgres_database': form.postgres_database.data, + 'postgres_username': form.postgres_username.data, + 'postgres_password': form.postgres_password.data, + } + + try: + db_config_manager.save_config(form_data) + flash('✅ Database configuration saved successfully!', 'success') + except Exception as e: + flash(f'❌ Failed to save configuration: {str(e)}', 'error') + + elif form.initialize_database.data: + # Initialize database + try: + success, message = db_config_manager.initialize_database( + create_sample_data=form.create_sample_data.data + ) + if success: + flash(f'✅ {message}', 'success') + else: + flash(f'❌ {message}', 'error') + except Exception as e: + flash(f'❌ Database initialization failed: {str(e)}', 'error') + + return render_template('database_setup.html', form=form, current_config=current_config) + + +@app.route('/admin/database-status') +@basic_auth.required +def database_status(): + """Admin page showing current database status and configuration""" + try: + from database import db_config + engine = db_config.engine + + # Test connection + with engine.connect() as conn: + result = conn.execute(text("SELECT 1")) + result.fetchone() + + connection_status = "✅ Connected" + + # Get database info + db_info = { + 'database_url': str(db_config.database_url), + 'database_type': os.getenv('DATABASE_TYPE', 'unknown'), + 'connection_status': connection_status + } + + # Try to get table count + try: + from database import Base + table_count = len(Base.metadata.tables) + db_info['table_count'] = table_count + except: + db_info['table_count'] = 'Unknown' + + except Exception as e: + db_info = { + 'database_url': 'Not configured', + 'database_type': 'Unknown', + 'connection_status': f'❌ Connection failed: {str(e)}', + 'table_count': 'Unknown' + } + + return render_template('database_status.html', db_info=db_info) + + if __name__ == "__main__": app.run(host='0.0.0.0', port=5000, debug=True) diff --git a/motm_app/templates/database_setup.html b/motm_app/templates/database_setup.html new file mode 100644 index 0000000..89033a4 --- /dev/null +++ b/motm_app/templates/database_setup.html @@ -0,0 +1,260 @@ +{% extends "bootstrap/base.html" %} + +{% block title %}Database Setup - MOTM Admin{% endblock %} + +{% block head %} +{{ super() }} + +{% endblock %} + +{% block content %} +
+
+
+

Database Setup & Configuration

+

Configure and initialize the database for the MOTM application.

+ + +
+

Current Configuration

+

Database Type: {{ current_config.database_type|title }}

+ {% if current_config.database_type == 'sqlite' %} +

Database File: {{ current_config.sqlite_database_path }}

+ {% elif current_config.database_type == 'mysql' %} +

Host: {{ current_config.mysql_host }}:{{ current_config.mysql_port }}

+

Database: {{ current_config.mysql_database }}

+

Username: {{ current_config.mysql_username }}

+ {% elif current_config.database_type == 'postgresql' %} +

Host: {{ current_config.postgres_host }}:{{ current_config.postgres_port }}

+

Database: {{ current_config.postgres_database }}

+

Username: {{ current_config.postgres_username }}

+ {% endif %} +
+ + + {% with messages = get_flashed_messages(with_categories=true) %} + {% if messages %} + {% for category, message in messages %} + + {% endfor %} + {% endif %} + {% endwith %} + + +
+ {{ form.hidden_tag() }} + + +
+

Database Type

+
+ {{ form.database_type.label(class="control-label") }} + {{ form.database_type(class="form-control") }} +
+
+ + +
+

SQLite Configuration

+
+ {{ form.sqlite_database_path.label(class="control-label") }} + {{ form.sqlite_database_path(class="form-control") }} + Path to the SQLite database file +
+
+ + +
+

MySQL/MariaDB Configuration

+
+
+
+ {{ form.mysql_host.label(class="control-label") }} + {{ form.mysql_host(class="form-control") }} +
+
+
+
+ {{ form.mysql_port.label(class="control-label") }} + {{ form.mysql_port(class="form-control") }} +
+
+
+
+ {{ form.mysql_database.label(class="control-label") }} + {{ form.mysql_database(class="form-control") }} +
+
+
+
+ {{ form.mysql_username.label(class="control-label") }} + {{ form.mysql_username(class="form-control") }} +
+
+
+
+ {{ form.mysql_password.label(class="control-label") }} + {{ form.mysql_password(class="form-control") }} +
+
+
+
+ {{ form.mysql_charset.label(class="control-label") }} + {{ form.mysql_charset(class="form-control") }} +
+
+ + +
+

PostgreSQL Configuration

+
+
+
+ {{ form.postgres_host.label(class="control-label") }} + {{ form.postgres_host(class="form-control") }} +
+
+
+
+ {{ form.postgres_port.label(class="control-label") }} + {{ form.postgres_port(class="form-control") }} +
+
+
+
+ {{ form.postgres_database.label(class="control-label") }} + {{ form.postgres_database(class="form-control") }} +
+
+
+
+ {{ form.postgres_username.label(class="control-label") }} + {{ form.postgres_username(class="form-control") }} +
+
+
+
+ {{ form.postgres_password.label(class="control-label") }} + {{ form.postgres_password(class="form-control") }} +
+
+
+
+ + +
+

Setup Options

+
+
+ +
+
+
+
+ +
+
+
+ + +
+ {{ form.test_connection(class="btn btn-info") }} + {{ form.save_config(class="btn btn-primary") }} + {{ form.initialize_database(class="btn btn-success") }} +
+
+ + + +
+
+
+ + +{% endblock %} diff --git a/motm_app/templates/database_status.html b/motm_app/templates/database_status.html new file mode 100644 index 0000000..c6eeeeb --- /dev/null +++ b/motm_app/templates/database_status.html @@ -0,0 +1,162 @@ +{% extends "bootstrap/base.html" %} + +{% block title %}Database Status - MOTM Admin{% endblock %} + +{% block head %} +{{ super() }} + +{% endblock %} + +{% block content %} +
+
+
+

Database Status

+

Current database configuration and connection status.

+ + +
+

Database Information

+ +
+
Connection Status:
+
{{ db_info.connection_status }}
+
+ +
+
Database Type:
+
{{ db_info.database_type|title }}
+
+ +
+
Database URL:
+
{{ db_info.database_url }}
+
+ +
+
Tables Count:
+
{{ db_info.table_count }}
+
+
+ + + + + + {% if db_info.table_count != 'Unknown' and db_info.table_count > 0 %} +
+

Database Tables

+

The database contains {{ db_info.table_count }} tables. The following tables are available:

+
    +
  • players - Player information and details
  • +
  • clubs - Hockey club information
  • +
  • teams - Team information and league details
  • +
  • match_squad - Match squad selections
  • +
  • hockey_fixtures - Match fixtures and results
  • +
  • admin_settings - Application configuration
  • +
  • motm_votes - Man of the Match voting data
  • +
  • match_comments - Match comments and feedback
  • +
  • hockey_users - User authentication data
  • +
+
+ {% endif %} + + +
+

Configuration Help

+
+
+

SQLite

+

Best for development and small deployments. No server required.

+
    +
  • File-based database
  • +
  • No installation required
  • +
  • Good for testing
  • +
+
+
+

MySQL/MariaDB

+

Popular choice for web applications. Good performance and reliability.

+
    +
  • Server-based database
  • +
  • Good for production
  • +
  • Wide hosting support
  • +
+
+
+

PostgreSQL

+

Advanced features and excellent performance. Great for complex applications.

+
    +
  • Advanced SQL features
  • +
  • Excellent performance
  • +
  • Strong data integrity
  • +
+
+
+
+
+
+
+{% endblock %} diff --git a/motm_app/templates/index.html b/motm_app/templates/index.html index 0702075..d403f3e 100644 --- a/motm_app/templates/index.html +++ b/motm_app/templates/index.html @@ -55,6 +55,14 @@

Player of the Year

View season totals and Player of the Year standings

+ +

Database Setup

+

Configure and initialize the database

+
+ +

Database Status

+

View current database configuration and status

+