995 lines
47 KiB
Python
995 lines
47 KiB
Python
# encoding=utf-8
|
|
import pymysql
|
|
import os
|
|
import json
|
|
import hashlib, uuid
|
|
import datetime
|
|
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, DatabaseSetupForm, PlayerForm, ClubForm, TeamForm, DataImportForm
|
|
from db_config import sql_write, sql_write_static, sql_read, sql_read_static
|
|
from sqlalchemy import text
|
|
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'
|
|
basic_auth = BasicAuth(app)
|
|
|
|
|
|
@app.route('/')
|
|
def index():
|
|
"""Main index page for MOTM system"""
|
|
return render_template('index.html')
|
|
|
|
|
|
# ==================== PUBLIC VOTING SECTION ====================
|
|
|
|
@app.route('/motm/<randomUrlSuffix>')
|
|
def motm_vote(randomUrlSuffix):
|
|
"""Public voting page for Man of the Match and Dick of the Day"""
|
|
sql = "SELECT playerNumber, playerForenames, playerSurname, playerNickname FROM _hkfcC_matchSquad ORDER BY RAND()"
|
|
sql2 = "SELECT nextClub, nextTeam, nextDate, oppoLogo, hkfcLogo, currMotM, currDotD, nextFixture FROM motmAdminSettings"
|
|
rows = sql_read(sql)
|
|
nextInfo = sql_read_static(sql2)
|
|
|
|
# Handle empty results
|
|
if not nextInfo:
|
|
return render_template('error.html', message="Database not initialized. Please go to Database Setup to initialize the database.")
|
|
|
|
nextClub = nextInfo[0]['nextClub']
|
|
nextTeam = nextInfo[0]['nextTeam']
|
|
nextFixture = nextInfo[0]['nextFixture']
|
|
hkfcLogo = nextInfo[0]['hkfcLogo']
|
|
oppoLogo = nextInfo[0]['oppoLogo']
|
|
currMotM = nextInfo[0]['currMotM']
|
|
currDotD = nextInfo[0]['currDotD']
|
|
oppo = nextTeam
|
|
sql3 = "SELECT hockeyResults2021.hockeyFixtures.date, hockeyResults.motmAdminSettings.nextFixture FROM hockeyResults2021.hockeyFixtures INNER JOIN hockeyResults.motmAdminSettings ON hockeyResults2021.hockeyFixtures.fixtureNumber = hockeyResults.motmAdminSettings.nextFixture"
|
|
nextMatchDate = sql_read(sql3)
|
|
if not nextMatchDate:
|
|
return render_template('error.html', message="No fixtures found. Please initialize the database with sample data.")
|
|
nextDate = nextMatchDate[0]['date']
|
|
formatDate = datetime.strftime(nextDate, '%A, %d %B %Y')
|
|
|
|
sql3 = "SELECT playerPictureURL FROM _HKFC_players INNER JOIN hockeyResults.motmAdminSettings ON _HKFC_players.playerNumber=hockeyResults.motmAdminSettings.currMotM"
|
|
sql4 = "SELECT playerPictureURL FROM _HKFC_players INNER JOIN hockeyResults.motmAdminSettings ON _HKFC_players.playerNumber=hockeyResults.motmAdminSettings.currDotD"
|
|
motm = sql_read(sql3)
|
|
dotd = sql_read(sql4)
|
|
|
|
# Handle empty results
|
|
if not motm or not dotd:
|
|
return render_template('error.html', message="Player data not found. Please initialize the database with sample data.")
|
|
|
|
motmURL = motm[0]['playerPictureURL']
|
|
dotdURL = dotd[0]['playerPictureURL']
|
|
|
|
sql5 = "SELECT comment FROM _motmComments INNER JOIN hockeyResults.motmAdminSettings ON _motmComments.matchDate=hockeyResults.motmAdminSettings.nextDate ORDER BY RAND() LIMIT 1"
|
|
comment = sql_read(sql5)
|
|
if comment == "":
|
|
comment = "No comments added yet"
|
|
form = motmForm()
|
|
sql6 = "SELECT motmUrlSuffix FROM hockeyResults.motmAdminSettings WHERE userid='admin'"
|
|
urlSuff = sql_read_static(sql6)
|
|
if not urlSuff:
|
|
return render_template('error.html', message="Admin settings not found. Please initialize the database.")
|
|
randomSuff = urlSuff[0]['motmUrlSuffix']
|
|
print(randomSuff)
|
|
if randomSuff == randomUrlSuffix:
|
|
return render_template('motm_vote.html', data=rows, comment=comment, formatDate=formatDate, matchNumber=nextFixture, oppo=oppo, hkfcLogo=hkfcLogo, oppoLogo=oppoLogo, dotdURL=dotdURL, motmURL=motmURL, form=form)
|
|
else:
|
|
return render_template('error.html')
|
|
|
|
|
|
@app.route('/motm/comments', methods=['GET', 'POST'])
|
|
def match_comments():
|
|
"""Display and allow adding match comments"""
|
|
sql = "SELECT nextClub, nextTeam, nextDate, oppoLogo, hkfcLogo FROM motmAdminSettings"
|
|
row = sql_read_static(sql)
|
|
if not row:
|
|
return render_template('error.html', message="Database not initialized. Please go to Database Setup to initialize the database.")
|
|
|
|
_oppo = row[0]['nextClub']
|
|
commentDate = row[0]['nextDate'].strftime('%Y-%m-%d')
|
|
_matchDate = row[0]['nextDate'].strftime('%Y_%m_%d')
|
|
hkfcLogo = row[0]['hkfcLogo']
|
|
oppoLogo = row[0]['oppoLogo']
|
|
if request.method == 'POST':
|
|
_comment = request.form['matchComment']
|
|
if _comment != 'Optional comments added here':
|
|
_fixed_comment = _comment.replace("'", "\\'")
|
|
sql3 = "INSERT INTO _motmComments (matchDate, opposition, comment) VALUES ('" + commentDate + "', '" + _oppo + "', '" + _fixed_comment + "')"
|
|
sql_write(sql3)
|
|
sql = "SELECT comment FROM _motmComments WHERE matchDate='" + _matchDate + "' ORDER BY RAND()"
|
|
comments = sql_read(sql)
|
|
return render_template('match_comments.html', comments=comments, hkfcLogo=hkfcLogo, oppoLogo=oppoLogo)
|
|
|
|
|
|
@app.route('/motm/vote-thanks', methods=['POST'])
|
|
def vote_thanks():
|
|
"""Process MOTM/DotD votes and comments"""
|
|
try:
|
|
_motm = request.form['motmVote']
|
|
_dotd = request.form['dotdVote']
|
|
_comments = request.form['motmComment']
|
|
_fixed_comments = _comments.replace("'", "\\'")
|
|
_matchDate = request.form['matchNumber']
|
|
_oppo = request.form['oppo']
|
|
|
|
if _motm and _dotd and request.method == 'POST':
|
|
sql = "INSERT INTO _hkfc_c_motm (playerNumber, playerName, motmTotal, motm_" + _matchDate + ") SELECT playerNumber, playerNickname, '1', '1' FROM _HKFC_players WHERE playerNumber='" + _motm + "' ON DUPLICATE KEY UPDATE motmTotal = motmTotal + 1, motm_" + _matchDate + " = motm_" + _matchDate + " + 1"
|
|
sql2 = "INSERT INTO _hkfc_c_motm (playerNumber, playerName, dotdTotal, dotd_" + _matchDate + ") SELECT playerNumber, playerNickname, '1', '1' FROM _HKFC_players WHERE playerNumber='" + _dotd + "' ON DUPLICATE KEY UPDATE dotdTotal = dotdTotal + 1, dotd_" + _matchDate + " = dotd_" + _matchDate + " + 1"
|
|
if _comments == "":
|
|
print("No comment")
|
|
elif _comments == "Optional comments added here":
|
|
print("No comment")
|
|
else:
|
|
sql3 = "INSERT INTO _motmComments (_matchDate, opposition, comment) VALUES ('" + _matchDate + "', '" + _oppo + "', '" + _fixed_comments + "')"
|
|
sql_write(sql3)
|
|
sql_write(sql)
|
|
sql_write(sql2)
|
|
return render_template('vote_thanks.html')
|
|
else:
|
|
return 'Ouch ... something went wrong here'
|
|
except Exception as e:
|
|
print(e)
|
|
finally:
|
|
print('Votes cast')
|
|
|
|
|
|
# ==================== ADMIN SECTION ====================
|
|
|
|
@app.route('/admin/motm', methods=['GET', 'POST'])
|
|
@basic_auth.required
|
|
def motm_admin():
|
|
"""Admin page for managing MOTM settings"""
|
|
form = adminSettingsForm2()
|
|
prevFixture = mySettings('prevFixture')
|
|
if prevFixture is None:
|
|
prevFixture = '1'
|
|
else:
|
|
prevFixture = str(prevFixture)
|
|
if request.method == 'POST':
|
|
if form.saveButton.data:
|
|
print('Saved')
|
|
else:
|
|
print('Activated')
|
|
_nextTeam = request.form['nextOppoTeam']
|
|
_nextMatchDate = request.form['nextMatchDate']
|
|
_currMotM = request.form['currMotM']
|
|
_currDotD = request.form['currDotD']
|
|
sql1 = "SELECT club FROM _clubTeams WHERE displayName='" + _nextTeam + "'"
|
|
_nextClubName = sql_read_static(sql1)
|
|
if not _nextClubName:
|
|
flash('Error: Club not found for team ' + _nextTeam, 'error')
|
|
return redirect(url_for('motm_admin'))
|
|
_nextClub = _nextClubName[0]['club']
|
|
sql = "UPDATE motmAdminSettings SET nextDate='" + _nextMatchDate + "', nextClub='" + _nextClub + "', nextTeam='" + _nextTeam + "', currMotM=" + _currMotM + ", currDotD=" + _currDotD + ""
|
|
sql_write_static(sql)
|
|
sql2 = "UPDATE motmAdminSettings INNER JOIN mensHockeyClubs ON motmAdminSettings.nextClub = mensHockeyClubs.hockeyClub SET motmAdminSettings.oppoLogo = mensHockeyClubs.logoURL WHERE mensHockeyClubs.hockeyClub='" + _nextClub + "'"
|
|
sql_write_static(sql2)
|
|
if form.saveButton.data:
|
|
flash('Settings saved!')
|
|
urlSuffix = randomUrlSuffix(8)
|
|
print(urlSuffix)
|
|
sql3 = "UPDATE motmAdminSettings SET motmUrlSuffix='" + urlSuffix + "' WHERE userid='admin'"
|
|
sql_write_static(sql3)
|
|
flash('MotM URL https://hockey.ervine.cloud/motm/'+urlSuffix)
|
|
elif form.activateButton.data:
|
|
# Generate a fixture number based on the date
|
|
_nextFixture = _nextMatchDate.replace('-', '')
|
|
sql4 = "ALTER TABLE _hkfc_c_motm ADD COLUMN motm_" + _nextFixture + " smallint DEFAULT 0, ADD COLUMN dotd_" + _nextFixture + " smallint DEFAULT 0, ADD COLUMN assists_" + _nextFixture + " smallint DEFAULT 0, ADD COLUMN goals_" + _nextFixture + " smallint DEFAULT 0 "
|
|
sql_write(sql4)
|
|
sql5 = "SELECT motmUrlSuffix FROM motmAdminSettings WHERE userid='admin'"
|
|
tempSuffix = sql_read_static(sql5)
|
|
if not tempSuffix:
|
|
flash('Error: Admin settings not found', 'error')
|
|
return redirect(url_for('motm_admin'))
|
|
currSuffix = tempSuffix[0]['motmUrlSuffix']
|
|
print(currSuffix)
|
|
flash('Man of the Match vote is now activated')
|
|
flash('MotM URL https://hockey.ervine.cloud/motm/'+currSuffix)
|
|
else:
|
|
flash('Something went wrong - check with Smithers')
|
|
|
|
# Load current settings to populate the form
|
|
sql_current = "SELECT nextDate FROM motmAdminSettings WHERE userid='admin'"
|
|
current_settings = sql_read_static(sql_current)
|
|
if current_settings:
|
|
from datetime import datetime
|
|
try:
|
|
current_date = datetime.strptime(current_settings[0]['nextDate'], '%Y-%m-%d').date()
|
|
form.nextMatchDate.data = current_date
|
|
except:
|
|
pass
|
|
sql4 = "SELECT hockeyClub FROM mensHockeyClubs ORDER BY hockeyClub"
|
|
sql5 = "SELECT nextClub, oppoLogo FROM motmAdminSettings"
|
|
sql6 = "SELECT playerNumber, playerForenames, playerSurname FROM _hkfcC_matchSquad_" + prevFixture + " ORDER BY playerForenames"
|
|
clubs = sql_read_static(sql4)
|
|
settings = sql_read_static(sql5)
|
|
players = sql_read(sql6)
|
|
|
|
# Handle empty results gracefully
|
|
if not clubs:
|
|
clubs = []
|
|
if not settings:
|
|
settings = [{'nextClub': 'Unknown', 'oppoLogo': '/static/images/default_logo.png'}]
|
|
if not players:
|
|
players = []
|
|
|
|
form.nextOppoClub.choices = [(oppo['hockeyClub'], oppo['hockeyClub']) for oppo in clubs]
|
|
form.currMotM.choices = [(player['playerNumber'], player['playerForenames'] + " " + player['playerSurname']) for player in players]
|
|
form.currDotD.choices = [(player['playerNumber'], player['playerForenames'] + " " + player['playerSurname']) for player in players]
|
|
clubLogo = settings[0]['oppoLogo']
|
|
|
|
return render_template('motm_admin.html', form=form, nextOppoLogo=clubLogo)
|
|
|
|
|
|
@app.route('/admin/players', methods=['GET'])
|
|
@basic_auth.required
|
|
def player_management():
|
|
"""Admin page for managing players"""
|
|
sql = text("SELECT playerNumber, playerForenames, playerSurname, playerNickname, playerTeam FROM _HKFC_players ORDER BY playerNumber")
|
|
players = sql_read(sql)
|
|
return render_template('player_management.html', players=players)
|
|
|
|
|
|
@app.route('/admin/players/add', methods=['GET', 'POST'])
|
|
@basic_auth.required
|
|
def add_player():
|
|
"""Add a new player"""
|
|
form = PlayerForm()
|
|
|
|
if form.validate_on_submit():
|
|
if form.save_player.data:
|
|
# Check if player number already exists
|
|
sql_check = text("SELECT playerNumber FROM _HKFC_players WHERE playerNumber = :player_number")
|
|
existing = sql_read(sql_check, {'player_number': form.player_number.data})
|
|
|
|
if existing:
|
|
flash('Player number already exists!', 'error')
|
|
return render_template('add_player.html', form=form)
|
|
|
|
# Insert new player
|
|
sql = text("INSERT INTO _HKFC_players (playerNumber, playerForenames, playerSurname, playerNickname, playerTeam) VALUES (:player_number, :forenames, :surname, :nickname, :team)")
|
|
sql_write(sql, {
|
|
'player_number': form.player_number.data,
|
|
'forenames': form.player_forenames.data,
|
|
'surname': form.player_surname.data,
|
|
'nickname': form.player_nickname.data,
|
|
'team': form.player_team.data
|
|
})
|
|
flash('Player added successfully!', 'success')
|
|
return redirect(url_for('player_management'))
|
|
elif form.cancel.data:
|
|
return redirect(url_for('player_management'))
|
|
|
|
return render_template('add_player.html', form=form)
|
|
|
|
|
|
@app.route('/admin/players/edit/<int:player_number>', methods=['GET', 'POST'])
|
|
@basic_auth.required
|
|
def edit_player(player_number):
|
|
"""Edit an existing player"""
|
|
form = PlayerForm()
|
|
|
|
if request.method == 'GET':
|
|
# Load player data
|
|
sql = text("SELECT playerNumber, playerForenames, playerSurname, playerNickname, playerTeam FROM _HKFC_players WHERE playerNumber = :player_number")
|
|
player_data = sql_read(sql, {'player_number': player_number})
|
|
|
|
if not player_data:
|
|
flash('Player not found!', 'error')
|
|
return redirect(url_for('player_management'))
|
|
|
|
player = player_data[0]
|
|
form.player_number.data = player['playerNumber']
|
|
form.player_forenames.data = player['playerForenames']
|
|
form.player_surname.data = player['playerSurname']
|
|
form.player_nickname.data = player['playerNickname']
|
|
form.player_team.data = player['playerTeam']
|
|
|
|
if form.validate_on_submit():
|
|
if form.save_player.data:
|
|
# Update player
|
|
sql = text("UPDATE _HKFC_players SET playerForenames = :forenames, playerSurname = :surname, playerNickname = :nickname, playerTeam = :team WHERE playerNumber = :player_number")
|
|
sql_write(sql, {
|
|
'forenames': form.player_forenames.data,
|
|
'surname': form.player_surname.data,
|
|
'nickname': form.player_nickname.data,
|
|
'team': form.player_team.data,
|
|
'player_number': player_number
|
|
})
|
|
flash('Player updated successfully!', 'success')
|
|
return redirect(url_for('player_management'))
|
|
elif form.cancel.data:
|
|
return redirect(url_for('player_management'))
|
|
|
|
return render_template('edit_player.html', form=form, player_number=player_number)
|
|
|
|
|
|
@app.route('/admin/players/delete/<int:player_number>', methods=['POST'])
|
|
@basic_auth.required
|
|
def delete_player(player_number):
|
|
"""Delete a player"""
|
|
sql = text("DELETE FROM _HKFC_players WHERE playerNumber = :player_number")
|
|
sql_write(sql, {'player_number': player_number})
|
|
flash('Player deleted successfully!', 'success')
|
|
return redirect(url_for('player_management'))
|
|
|
|
|
|
@app.route('/admin/squad', methods=['GET'])
|
|
@basic_auth.required
|
|
def match_squad():
|
|
"""Admin page for managing match squad"""
|
|
sql = text("SELECT playerNumber, playerForenames, playerSurname, playerNickname, playerTeam FROM _HKFC_players ORDER BY playerTeam, playerNumber")
|
|
players = sql_read(sql)
|
|
return render_template('match_squad.html', players=players)
|
|
|
|
|
|
# ==================== CLUB MANAGEMENT ====================
|
|
|
|
@app.route('/admin/clubs', methods=['GET'])
|
|
@basic_auth.required
|
|
def club_management():
|
|
"""Admin page for managing clubs"""
|
|
sql = text("SELECT id, hockey_club, logo_url FROM clubs ORDER BY hockey_club")
|
|
clubs = sql_read(sql)
|
|
return render_template('club_management.html', clubs=clubs)
|
|
|
|
|
|
@app.route('/admin/clubs/add', methods=['GET', 'POST'])
|
|
@basic_auth.required
|
|
def add_club():
|
|
"""Add a new club"""
|
|
form = ClubForm()
|
|
|
|
if form.validate_on_submit():
|
|
if form.save_club.data:
|
|
# Check if club already exists
|
|
sql_check = text("SELECT hockey_club FROM clubs WHERE hockey_club = :club_name")
|
|
existing = sql_read(sql_check, {'club_name': form.hockey_club.data})
|
|
|
|
if existing:
|
|
flash('Club already exists!', 'error')
|
|
return render_template('add_club.html', form=form)
|
|
|
|
# Insert new club
|
|
sql = text("INSERT INTO clubs (hockey_club, logo_url) VALUES (:club_name, :logo_url)")
|
|
sql_write(sql, {
|
|
'club_name': form.hockey_club.data,
|
|
'logo_url': form.logo_url.data
|
|
})
|
|
flash('Club added successfully!', 'success')
|
|
return redirect(url_for('club_management'))
|
|
elif form.cancel.data:
|
|
return redirect(url_for('club_management'))
|
|
|
|
return render_template('add_club.html', form=form)
|
|
|
|
|
|
@app.route('/admin/clubs/edit/<int:club_id>', methods=['GET', 'POST'])
|
|
@basic_auth.required
|
|
def edit_club(club_id):
|
|
"""Edit an existing club"""
|
|
form = ClubForm()
|
|
|
|
if request.method == 'GET':
|
|
# Load club data
|
|
sql = text("SELECT id, hockey_club, logo_url FROM clubs WHERE id = :club_id")
|
|
club_data = sql_read(sql, {'club_id': club_id})
|
|
|
|
if not club_data:
|
|
flash('Club not found!', 'error')
|
|
return redirect(url_for('club_management'))
|
|
|
|
club = club_data[0]
|
|
form.hockey_club.data = club['hockey_club']
|
|
form.logo_url.data = club['logo_url']
|
|
|
|
if form.validate_on_submit():
|
|
if form.save_club.data:
|
|
# Update club
|
|
sql = text("UPDATE clubs SET hockey_club = :club_name, logo_url = :logo_url WHERE id = :club_id")
|
|
sql_write(sql, {
|
|
'club_name': form.hockey_club.data,
|
|
'logo_url': form.logo_url.data,
|
|
'club_id': club_id
|
|
})
|
|
flash('Club updated successfully!', 'success')
|
|
return redirect(url_for('club_management'))
|
|
elif form.cancel.data:
|
|
return redirect(url_for('club_management'))
|
|
|
|
return render_template('edit_club.html', form=form, club_id=club_id)
|
|
|
|
|
|
@app.route('/admin/clubs/delete/<int:club_id>', methods=['POST'])
|
|
@basic_auth.required
|
|
def delete_club(club_id):
|
|
"""Delete a club"""
|
|
sql = text("DELETE FROM clubs WHERE id = :club_id")
|
|
sql_write(sql, {'club_id': club_id})
|
|
flash('Club deleted successfully!', 'success')
|
|
return redirect(url_for('club_management'))
|
|
|
|
|
|
# ==================== TEAM MANAGEMENT ====================
|
|
|
|
@app.route('/admin/teams', methods=['GET'])
|
|
@basic_auth.required
|
|
def team_management():
|
|
"""Admin page for managing teams"""
|
|
sql = text("SELECT id, club, team, display_name, league FROM teams ORDER BY club, team")
|
|
teams = sql_read(sql)
|
|
return render_template('team_management.html', teams=teams)
|
|
|
|
|
|
@app.route('/admin/teams/add', methods=['GET', 'POST'])
|
|
@basic_auth.required
|
|
def add_team():
|
|
"""Add a new team"""
|
|
form = TeamForm()
|
|
|
|
if form.validate_on_submit():
|
|
if form.save_team.data:
|
|
# Check if team already exists
|
|
sql_check = text("SELECT club, team FROM teams WHERE club = :club AND team = :team")
|
|
existing = sql_read(sql_check, {'club': form.club.data, 'team': form.team.data})
|
|
|
|
if existing:
|
|
flash('Team already exists!', 'error')
|
|
return render_template('add_team.html', form=form)
|
|
|
|
# Insert new team
|
|
sql = text("INSERT INTO teams (club, team, display_name, league) VALUES (:club, :team, :display_name, :league)")
|
|
sql_write(sql, {
|
|
'club': form.club.data,
|
|
'team': form.team.data,
|
|
'display_name': form.display_name.data,
|
|
'league': form.league.data
|
|
})
|
|
flash('Team added successfully!', 'success')
|
|
return redirect(url_for('team_management'))
|
|
elif form.cancel.data:
|
|
return redirect(url_for('team_management'))
|
|
|
|
return render_template('add_team.html', form=form)
|
|
|
|
|
|
@app.route('/admin/teams/edit/<int:team_id>', methods=['GET', 'POST'])
|
|
@basic_auth.required
|
|
def edit_team(team_id):
|
|
"""Edit an existing team"""
|
|
form = TeamForm()
|
|
|
|
if request.method == 'GET':
|
|
# Load team data
|
|
sql = text("SELECT id, club, team, display_name, league FROM teams WHERE id = :team_id")
|
|
team_data = sql_read(sql, {'team_id': team_id})
|
|
|
|
if not team_data:
|
|
flash('Team not found!', 'error')
|
|
return redirect(url_for('team_management'))
|
|
|
|
team = team_data[0]
|
|
form.club.data = team['club']
|
|
form.team.data = team['team']
|
|
form.display_name.data = team['display_name']
|
|
form.league.data = team['league']
|
|
|
|
if form.validate_on_submit():
|
|
if form.save_team.data:
|
|
# Update team
|
|
sql = text("UPDATE teams SET club = :club, team = :team, display_name = :display_name, league = :league WHERE id = :team_id")
|
|
sql_write(sql, {
|
|
'club': form.club.data,
|
|
'team': form.team.data,
|
|
'display_name': form.display_name.data,
|
|
'league': form.league.data,
|
|
'team_id': team_id
|
|
})
|
|
flash('Team updated successfully!', 'success')
|
|
return redirect(url_for('team_management'))
|
|
elif form.cancel.data:
|
|
return redirect(url_for('team_management'))
|
|
|
|
return render_template('edit_team.html', form=form, team_id=team_id)
|
|
|
|
|
|
@app.route('/admin/teams/delete/<int:team_id>', methods=['POST'])
|
|
@basic_auth.required
|
|
def delete_team(team_id):
|
|
"""Delete a team"""
|
|
sql = text("DELETE FROM teams WHERE id = :team_id")
|
|
sql_write(sql, {'team_id': team_id})
|
|
flash('Team deleted successfully!', 'success')
|
|
return redirect(url_for('team_management'))
|
|
|
|
|
|
# ==================== DATA IMPORT ====================
|
|
|
|
@app.route('/admin/import', methods=['GET', 'POST'])
|
|
@basic_auth.required
|
|
def data_import():
|
|
"""Import data from Hong Kong Hockey Association"""
|
|
form = DataImportForm()
|
|
|
|
if form.validate_on_submit():
|
|
if form.import_data.data:
|
|
imported_clubs = 0
|
|
imported_teams = 0
|
|
imported_players = 0
|
|
|
|
if form.import_clubs.data:
|
|
# Import clubs based on Hong Kong Hockey Association data
|
|
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'},
|
|
{'hockey_club': 'SSSC', 'logo_url': '/static/images/sssc_logo.png'},
|
|
{'hockey_club': 'Dragons', 'logo_url': '/static/images/dragons_logo.png'},
|
|
{'hockey_club': 'Kai Tak', 'logo_url': '/static/images/kaitak_logo.png'},
|
|
{'hockey_club': 'RHOBA', 'logo_url': '/static/images/rhoba_logo.png'},
|
|
{'hockey_club': 'Elite', 'logo_url': '/static/images/elite_logo.png'},
|
|
{'hockey_club': 'Aquila', 'logo_url': '/static/images/aquila_logo.png'},
|
|
{'hockey_club': 'HKJ', 'logo_url': '/static/images/hkj_logo.png'},
|
|
{'hockey_club': 'Sirius', 'logo_url': '/static/images/sirius_logo.png'},
|
|
{'hockey_club': 'Shaheen', 'logo_url': '/static/images/shaheen_logo.png'},
|
|
{'hockey_club': 'Diocesan', 'logo_url': '/static/images/diocesan_logo.png'},
|
|
{'hockey_club': 'Rhino', 'logo_url': '/static/images/rhino_logo.png'},
|
|
{'hockey_club': 'Khalsa', 'logo_url': '/static/images/khalsa_logo.png'},
|
|
{'hockey_club': 'HKCC', 'logo_url': '/static/images/hkcc_logo.png'},
|
|
{'hockey_club': 'Police', 'logo_url': '/static/images/police_logo.png'},
|
|
{'hockey_club': 'Recreio', 'logo_url': '/static/images/recreio_logo.png'},
|
|
{'hockey_club': 'CSD', 'logo_url': '/static/images/csd_logo.png'},
|
|
{'hockey_club': 'Dutch', 'logo_url': '/static/images/dutch_logo.png'},
|
|
{'hockey_club': 'HKUHC', 'logo_url': '/static/images/hkuhc_logo.png'},
|
|
{'hockey_club': 'Kaitiaki', 'logo_url': '/static/images/kaitiaki_logo.png'},
|
|
{'hockey_club': 'Antlers', 'logo_url': '/static/images/antlers_logo.png'},
|
|
{'hockey_club': 'Marcellin', 'logo_url': '/static/images/marcellin_logo.png'},
|
|
{'hockey_club': 'Skyers', 'logo_url': '/static/images/skyers_logo.png'},
|
|
{'hockey_club': 'JR', 'logo_url': '/static/images/jr_logo.png'},
|
|
{'hockey_club': 'IUHK', 'logo_url': '/static/images/iuhk_logo.png'},
|
|
{'hockey_club': '144U', 'logo_url': '/static/images/144u_logo.png'},
|
|
{'hockey_club': 'HKU', 'logo_url': '/static/images/hku_logo.png'},
|
|
]
|
|
|
|
for club_data in clubs_data:
|
|
# Check if club already exists
|
|
sql_check = text("SELECT hockey_club FROM clubs WHERE hockey_club = :club_name")
|
|
existing = sql_read(sql_check, {'club_name': club_data['hockey_club']})
|
|
|
|
if not existing:
|
|
sql = text("INSERT INTO clubs (hockey_club, logo_url) VALUES (:club_name, :logo_url)")
|
|
sql_write(sql, club_data)
|
|
imported_clubs += 1
|
|
|
|
if form.import_teams.data:
|
|
# Import teams based on Hong Kong Hockey Association divisions
|
|
teams_data = [
|
|
# Premier Division
|
|
{'club': 'HKFC', 'team': 'A', 'display_name': 'HKFC A', 'league': 'Premier Division'},
|
|
{'club': 'KCC', 'team': 'A', 'display_name': 'KCC A', 'league': 'Premier Division'},
|
|
{'club': 'USRC', 'team': 'A', 'display_name': 'USRC A', 'league': 'Premier Division'},
|
|
{'club': 'Valley', 'team': 'A', 'display_name': 'Valley A', 'league': 'Premier Division'},
|
|
|
|
# 1st Division
|
|
{'club': 'HKFC', 'team': 'B', 'display_name': 'HKFC B', 'league': '1st Division'},
|
|
{'club': 'KCC', 'team': 'B', 'display_name': 'KCC B', 'league': '1st Division'},
|
|
{'club': 'USRC', 'team': 'B', 'display_name': 'USRC B', 'league': '1st Division'},
|
|
{'club': 'Valley', 'team': 'B', 'display_name': 'Valley B', 'league': '1st Division'},
|
|
|
|
# 2nd Division
|
|
{'club': 'HKFC', 'team': 'C', 'display_name': 'HKFC C', 'league': '2nd Division'},
|
|
{'club': 'KCC', 'team': 'C', 'display_name': 'KCC C', 'league': '2nd Division'},
|
|
{'club': 'USRC', 'team': 'C', 'display_name': 'USRC C', 'league': '2nd Division'},
|
|
{'club': 'Valley', 'team': 'C', 'display_name': 'Valley C', 'league': '2nd Division'},
|
|
|
|
# 3rd Division
|
|
{'club': 'SSSC', 'team': 'C', 'display_name': 'SSSC C', 'league': '3rd Division'},
|
|
{'club': 'Dragons', 'team': 'A', 'display_name': 'Dragons A', 'league': '3rd Division'},
|
|
{'club': 'Kai Tak', 'team': 'B', 'display_name': 'Kai Tak B', 'league': '3rd Division'},
|
|
{'club': 'RHOBA', 'team': 'A', 'display_name': 'RHOBA A', 'league': '3rd Division'},
|
|
{'club': 'Elite', 'team': 'B', 'display_name': 'Elite B', 'league': '3rd Division'},
|
|
{'club': 'HKFC', 'team': 'F', 'display_name': 'HKFC F', 'league': '3rd Division'},
|
|
{'club': 'Aquila', 'team': 'A', 'display_name': 'Aquila A', 'league': '3rd Division'},
|
|
{'club': 'HKJ', 'team': 'B', 'display_name': 'HKJ B', 'league': '3rd Division'},
|
|
{'club': 'Sirius', 'team': 'A', 'display_name': 'Sirius A', 'league': '3rd Division'},
|
|
{'club': 'Shaheen', 'team': 'B', 'display_name': 'Shaheen B', 'league': '3rd Division'},
|
|
{'club': 'RHOBA', 'team': 'B', 'display_name': 'RHOBA B', 'league': '3rd Division'},
|
|
|
|
# 4th Division
|
|
{'club': 'Khalsa', 'team': 'C', 'display_name': 'Khalsa C', 'league': '4th Division'},
|
|
{'club': 'HKCC', 'team': 'C', 'display_name': 'HKCC C', 'league': '4th Division'},
|
|
{'club': 'Valley', 'team': 'D', 'display_name': 'Valley D', 'league': '4th Division'},
|
|
{'club': 'Police', 'team': 'A', 'display_name': 'Police A', 'league': '4th Division'},
|
|
{'club': 'Recreio', 'team': 'A', 'display_name': 'Recreio A', 'league': '4th Division'},
|
|
{'club': 'CSD', 'team': 'A', 'display_name': 'CSD A', 'league': '4th Division'},
|
|
{'club': 'HKFC', 'team': 'G', 'display_name': 'HKFC G', 'league': '4th Division'},
|
|
{'club': 'Dutch', 'team': 'B', 'display_name': 'Dutch B', 'league': '4th Division'},
|
|
{'club': 'RHOBA', 'team': 'C', 'display_name': 'RHOBA C', 'league': '4th Division'},
|
|
{'club': 'HKUHC', 'team': 'A', 'display_name': 'HKUHC A', 'league': '4th Division'},
|
|
{'club': 'Kaitiaki', 'team': 'A', 'display_name': 'Kaitiaki', 'league': '4th Division'},
|
|
|
|
# 5th Division
|
|
{'club': 'KCC', 'team': 'D', 'display_name': 'KCC D', 'league': '5th Division'},
|
|
{'club': 'Kai Tak', 'team': 'C', 'display_name': 'Kai Tak C', 'league': '5th Division'},
|
|
{'club': 'Dragons', 'team': 'B', 'display_name': 'Dragons B', 'league': '5th Division'},
|
|
{'club': 'Antlers', 'team': 'C', 'display_name': 'Antlers C', 'league': '5th Division'},
|
|
{'club': 'Valley', 'team': 'E', 'display_name': 'Valley E', 'league': '5th Division'},
|
|
{'club': 'Elite', 'team': 'C', 'display_name': 'Elite C', 'league': '5th Division'},
|
|
{'club': 'HKFC', 'team': 'H', 'display_name': 'HKFC H', 'league': '5th Division'},
|
|
{'club': 'Aquila', 'team': 'B', 'display_name': 'Aquila B', 'league': '5th Division'},
|
|
{'club': 'Sirius', 'team': 'B', 'display_name': 'Sirius B', 'league': '5th Division'},
|
|
{'club': 'Marcellin', 'team': 'A', 'display_name': 'Marcellin A', 'league': '5th Division'},
|
|
{'club': 'Recreio', 'team': 'B', 'display_name': 'Recreio B', 'league': '5th Division'},
|
|
{'club': 'Diocesan', 'team': 'B', 'display_name': 'Diocesan B', 'league': '5th Division'},
|
|
|
|
# 6th Division
|
|
{'club': 'Rhino', 'team': 'B', 'display_name': 'Rhino B', 'league': '6th Division'},
|
|
{'club': 'Skyers', 'team': 'A', 'display_name': 'Skyers A', 'league': '6th Division'},
|
|
{'club': 'JR', 'team': 'A', 'display_name': 'JR', 'league': '6th Division'},
|
|
{'club': 'HKCC', 'team': 'D', 'display_name': 'HKCC D', 'league': '6th Division'},
|
|
{'club': 'KCC', 'team': 'E', 'display_name': 'KCC E', 'league': '6th Division'},
|
|
{'club': 'HKJ', 'team': 'C', 'display_name': 'HKJ C', 'league': '6th Division'},
|
|
{'club': 'IUHK', 'team': 'A', 'display_name': 'IUHK A', 'league': '6th Division'},
|
|
{'club': 'Valley', 'team': 'F', 'display_name': 'Valley F', 'league': '6th Division'},
|
|
{'club': '144U', 'team': 'A', 'display_name': '144U A', 'league': '6th Division'},
|
|
{'club': 'HKU', 'team': 'A', 'display_name': 'HKU A', 'league': '6th Division'},
|
|
]
|
|
|
|
for team_data in teams_data:
|
|
# Check if team already exists
|
|
sql_check = text("SELECT club, team FROM teams WHERE club = :club AND team = :team")
|
|
existing = sql_read(sql_check, {'club': team_data['club'], 'team': team_data['team']})
|
|
|
|
if not existing:
|
|
sql = text("INSERT INTO teams (club, team, display_name, league) VALUES (:club, :team, :display_name, :league)")
|
|
sql_write(sql, team_data)
|
|
imported_teams += 1
|
|
|
|
if form.import_players.data:
|
|
# Import sample players for HKFC C team
|
|
players_data = [
|
|
{'player_number': 1, 'player_forenames': 'John', 'player_surname': 'Smith', 'player_nickname': 'Smithers', 'player_team': 'HKFC C'},
|
|
{'player_number': 2, 'player_forenames': 'Mike', 'player_surname': 'Jones', 'player_nickname': 'Jonesy', 'player_team': 'HKFC C'},
|
|
{'player_number': 3, 'player_forenames': 'David', 'player_surname': 'Brown', 'player_nickname': 'Brownie', 'player_team': 'HKFC C'},
|
|
{'player_number': 4, 'player_forenames': 'Chris', 'player_surname': 'Wilson', 'player_nickname': 'Willy', 'player_team': 'HKFC C'},
|
|
{'player_number': 5, 'player_forenames': 'Tom', 'player_surname': 'Taylor', 'player_nickname': 'Tayls', 'player_team': 'HKFC C'},
|
|
]
|
|
|
|
for player_data in players_data:
|
|
# Check if player already exists
|
|
sql_check = text("SELECT playerNumber FROM _HKFC_players WHERE playerNumber = :player_number")
|
|
existing = sql_read(sql_check, {'player_number': player_data['player_number']})
|
|
|
|
if not existing:
|
|
sql = text("INSERT INTO _HKFC_players (playerNumber, playerForenames, playerSurname, playerNickname, playerTeam) VALUES (:player_number, :forenames, :surname, :nickname, :team)")
|
|
sql_write(sql, player_data)
|
|
imported_players += 1
|
|
|
|
flash(f'Import completed! {imported_clubs} clubs, {imported_teams} teams, {imported_players} players imported.', 'success')
|
|
return redirect(url_for('data_import'))
|
|
elif form.cancel.data:
|
|
return redirect(url_for('data_import'))
|
|
|
|
return render_template('data_import.html', form=form)
|
|
|
|
|
|
@app.route('/admin/squad/submit', methods=['POST'])
|
|
@basic_auth.required
|
|
def match_squad_submit():
|
|
"""Process squad selection"""
|
|
_playerNumbers = request.form.getlist('playerNumber')
|
|
for _playerNumber in _playerNumbers:
|
|
sql = "INSERT INTO _hkfcC_matchSquad (playerNumber, playerForenames, playerSurname, playerNickname) SELECT playerNumber, playerForenames, playerSurname, playerNickname FROM _HKFC_players WHERE playerNumber='" + _playerNumber + "'"
|
|
sql_write(sql)
|
|
sql2 = "SELECT playerNumber, playerForenames, playerSurname, playerNickname FROM _hkfcC_matchSquad"
|
|
players = sql_read(sql2)
|
|
table = matchSquadTable(players)
|
|
table.border = True
|
|
table.classes = ['table-striped', 'table-condensed', 'table-hover']
|
|
return render_template('match_squad_selected.html', table=table)
|
|
|
|
|
|
@app.route('/admin/squad/list')
|
|
@basic_auth.required
|
|
def match_squad_list():
|
|
"""Display current squad list"""
|
|
sql = "SELECT playerNumber, playerForenames, playerSurname, playerNickname FROM _hkfcC_matchSquad"
|
|
players = sql_read(sql)
|
|
table = matchSquadTable(players)
|
|
table.border = True
|
|
table.classes = ['table-striped', 'table-condensed', 'table-hover']
|
|
return render_template('match_squad_selected.html', table=table)
|
|
|
|
|
|
@app.route('/admin/squad/remove', methods=['POST'])
|
|
@basic_auth.required
|
|
def delPlayerFromSquad():
|
|
"""Remove player from squad"""
|
|
_playerNumber = request.args['playerNumber']
|
|
sql = "DELETE FROM _hkfcC_matchSquad WHERE playerNumber=" + _playerNumber + ""
|
|
sql_write(sql)
|
|
return render_template('player_removed.html', number=_playerNumber)
|
|
|
|
|
|
@app.route('/admin/squad/reset')
|
|
@basic_auth.required
|
|
def matchSquadReset():
|
|
"""Reset squad for new match"""
|
|
_matchNumber = str(mySettings('fixture'))
|
|
print(_matchNumber)
|
|
sql1 = "RENAME TABLE _hkfcC_matchSquad TO _hkfcC_matchSquad_" + _matchNumber + ""
|
|
sql2 = "CREATE TABLE _hkfcC_matchSquad (playerNumber smallint UNIQUE, playerForenames varchar(50), playerSurname varchar(30), playerNickname varchar(30) NOT NULL, PRIMARY KEY (playerNumber))"
|
|
sql3 = "UPDATE motmAdminSettings SET prevFixture='" + _matchNumber + "'"
|
|
sql_write(sql1)
|
|
sql_write(sql2)
|
|
sql_write_static(sql3)
|
|
return render_template('match_squad_reset.html')
|
|
|
|
|
|
@app.route('/admin/stats', methods=['GET', 'POST'])
|
|
@basic_auth.required
|
|
def stats_admin():
|
|
"""Admin page for managing goals and assists statistics"""
|
|
form = goalsAssistsForm()
|
|
sql = "SELECT date, homeTeam, awayTeam, venue, fixtureNumber FROM hockeyFixtures WHERE homeTeam='HKFC C' OR awayTeam='HKFC C'"
|
|
matches = sql_read(sql)
|
|
form.match.choices = [(match['fixtureNumber'], match['date']) for match in matches]
|
|
sql2 = "SELECT playerNumber, playerNickname FROM _hkfcC_matchSquad"
|
|
players = sql_read(sql2)
|
|
return render_template('goals_assists_admin.html', data=players, form=form)
|
|
|
|
|
|
@app.route('/admin/stats/submit', methods=['POST'])
|
|
@basic_auth.required
|
|
def goalsAssistsSubmit():
|
|
"""Process goals and assists statistics"""
|
|
try:
|
|
data = request.form
|
|
playerName = request.form.getlist('playerName')
|
|
playerNumber = request.form.getlist('playerNumber')
|
|
assists = request.form.getlist('assists')
|
|
goals = request.form.getlist('goals')
|
|
match = request.form['match']
|
|
for idx, player in enumerate(playerNumber):
|
|
sql = "INSERT INTO _hkfc_c_motm (playerNumber, playerName, assistsTotal, goalsTotal, assists_" + match + ", goals_" + match + ") SELECT playerNumber, playerNickname, '" + assists[idx] + "', '" + goals[idx] + "', '" + assists[idx] + "', '" + goals[idx] + "' FROM _HKFC_players WHERE playerNumber='" + player + "' ON DUPLICATE KEY UPDATE assistsTotal = assistsTotal + " + assists[idx] + ", goalsTotal = goalsTotal + " + goals[idx] + ", assists_" + match + " = " + assists[idx] + ", goals_" + match + " = " + goals[idx] + ""
|
|
sql_write(sql)
|
|
except Exception as e:
|
|
print(e)
|
|
finally:
|
|
return render_template('goals_thanks.html', data=data)
|
|
|
|
|
|
# ==================== API ENDPOINTS ====================
|
|
|
|
@app.route('/admin/api/team/<club>')
|
|
def admin_team_lookup(club):
|
|
"""API endpoint for team lookup by club"""
|
|
sql = "SELECT team FROM _clubTeams WHERE club='" + club + "'"
|
|
myteams = sql_read(sql)
|
|
return jsonify(myteams)
|
|
|
|
|
|
@app.route('/admin/api/logo/<club>')
|
|
def get_logo(club):
|
|
"""API endpoint for club logo lookup"""
|
|
sql = "SELECT logoURL FROM mensHockeyClubs WHERE hockeyClub='" + club + "'"
|
|
clubLogo = sql_read(sql)
|
|
return jsonify(clubLogo)
|
|
|
|
|
|
@app.route('/admin/api/fixture/<fixture>')
|
|
def admin_fixture_lookup(fixture):
|
|
"""API endpoint for fixture team lookup"""
|
|
sql = "SELECT homeTeam, awayTeam FROM hockeyFixtures WHERE fixtureNumber='" + fixture + "'"
|
|
myteams = sql_read(sql)
|
|
if not myteams:
|
|
return jsonify({'error': 'Fixture not found'})
|
|
if myteams[0]['homeTeam'].startswith("HKFC"):
|
|
nextOppo = myteams[0]['awayTeam']
|
|
else:
|
|
nextOppo = myteams[0]['homeTeam']
|
|
return jsonify(nextOppo)
|
|
|
|
|
|
@app.route('/admin/api/fixture/<fixture>/logo')
|
|
def admin_fixture_logo_lookup(fixture):
|
|
"""API endpoint for fixture logo lookup"""
|
|
sql = "SELECT homeTeam, awayTeam FROM hockeyFixtures WHERE fixtureNumber='" + fixture + "'"
|
|
myteams = sql_read(sql)
|
|
if not myteams:
|
|
return jsonify({'error': 'Fixture not found'})
|
|
if myteams[0]['homeTeam'].startswith("HKFC C"):
|
|
nextOppo = myteams[0]['awayTeam']
|
|
else:
|
|
nextOppo = myteams[0]['homeTeam']
|
|
sql2 = "SELECT club FROM _clubTeams WHERE displayName ='" + nextOppo + "'"
|
|
clubs = sql_read_static(sql2)
|
|
if not clubs:
|
|
return jsonify({'error': 'Club not found'})
|
|
clubName = clubs[0]['club']
|
|
sql3 = "SELECT logoUrl FROM mensHockeyClubs WHERE hockeyClub ='" + clubName + "'"
|
|
logo = sql_read_static(sql3)
|
|
if not logo:
|
|
return jsonify({'error': 'Logo not found'})
|
|
clubLogo = logo[0]['logoUrl']
|
|
return jsonify(clubLogo)
|
|
|
|
|
|
@app.route('/api/vote-results')
|
|
def vote_results():
|
|
"""API endpoint for voting results"""
|
|
_matchDate = str(mySettings('fixture'))
|
|
print(_matchDate)
|
|
sql = "SELECT playerName, motm_" + _matchDate + ", dotd_" + _matchDate + " FROM _hkfc_c_motm WHERE (motm_" + _matchDate + " > '0') OR (dotd_" + _matchDate + " > '0')"
|
|
print(sql)
|
|
rows = sql_read(sql)
|
|
print(rows)
|
|
return json.dumps(rows)
|
|
|
|
|
|
@app.route('/api/poty-results')
|
|
def poty_results():
|
|
"""API endpoint for Player of the Year results"""
|
|
sql = "SELECT playerName, motmTotal, dotdTotal FROM _hkfc_c_motm WHERE (motmTotal > '0') OR (dotdTotal > '0')"
|
|
print(sql)
|
|
rows = sql_read(sql)
|
|
return json.dumps(rows)
|
|
|
|
|
|
@app.route('/admin/voting')
|
|
@basic_auth.required
|
|
def voting_chart():
|
|
"""Admin page for viewing voting charts"""
|
|
matchDate = mySettings('fixture')
|
|
return render_template('vote_chart.html', _matchDate=matchDate)
|
|
|
|
|
|
@app.route('/admin/poty')
|
|
@basic_auth.required
|
|
def poty_chart():
|
|
"""Admin page for Player of the Year 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()
|
|
|
|
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')
|
|
|
|
# Load current configuration for display
|
|
current_config = db_config_manager.get_config_dict()
|
|
|
|
# Populate form with current configuration (only for GET requests or after POST processing)
|
|
for field_name, value in current_config.items():
|
|
if hasattr(form, field_name):
|
|
getattr(form, field_name).data = value
|
|
|
|
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:
|
|
# Reload database configuration to get latest settings
|
|
from database import DatabaseConfig
|
|
current_db_config = DatabaseConfig()
|
|
engine = current_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(current_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)
|