From 0402209290299e5436e734b9f5982d59056d4c18 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Mon, 7 Mar 2022 12:01:58 -0700 Subject: [PATCH 01/21] Add new fetch.js route --- app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app.js b/app.js index 9764a31..da69f40 100644 --- a/app.js +++ b/app.js @@ -15,6 +15,7 @@ var dataRouter = require('./routes/data'); var manageRouter = require('./routes/manage'); var authRouter = require('./routes/auth'); var aboutRouter = require('./routes/about'); +var fetchRouter = require('./routes/fetch'); var app = express(); @@ -53,6 +54,7 @@ app.use('/data', dataRouter); app.use('/manage', manageRouter); app.use('/auth', authRouter); app.use('/about', aboutRouter); +app.use('/fetch', fetchRouter); // catch 404 and forward to error handler From cc66467197e8384e132d7549b3d4bcbec3ec0b90 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Mon, 7 Mar 2022 12:21:17 -0700 Subject: [PATCH 02/21] Get seasons from a single request --- public/scripts/form.js | 14 +++++++--- public/scripts/index.js | 12 +++++++-- routes/fetch.js | 60 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 routes/fetch.js diff --git a/public/scripts/form.js b/public/scripts/form.js index 631b404..96dadc6 100644 --- a/public/scripts/form.js +++ b/public/scripts/form.js @@ -20,11 +20,17 @@ export async function populateSports(sportDropdown, selectedSportID = undefined) if(selectedSportIndex) sportDropdown.selectedIndex = selectedSportIndex; } -export async function populateSeasons(seasonDropdown, selectedSeasonID = undefined) { +export async function populateSeasons(seasonDropdown, selectedSeasonID = undefined, data = undefined) { seasonDropdown.innerHTML = ""; - - const seasonsList = await Data.getSeasons(); + let seasonsList; + + if(data) { + seasonsList = data.seasons; + } else { + seasonsList = await Data.getSeasons(); + } + console.log(data); let currentIndex = 0; let selectedSeasonIndex; seasonsList.forEach(season => { @@ -33,7 +39,7 @@ export async function populateSeasons(seasonDropdown, selectedSeasonID = undefin option.value = season.id; seasonDropdown.appendChild(option); - if(season.id == selectedSeasonID) selectedSeasonIndex = currentIndex; + if(season.id == selectedSeasonID || (data && season.id == data.latestGame.seasonID)) selectedSeasonIndex = currentIndex; currentIndex++; }); diff --git a/public/scripts/index.js b/public/scripts/index.js index 1b70ca3..a30d681 100644 --- a/public/scripts/index.js +++ b/public/scripts/index.js @@ -17,7 +17,15 @@ const manageButton = document.getElementById('manage-button'); async function initializeForm() { - let latestGame; + const data = await (await fetch(`/fetch/index/dropdown`)).json(); + + await Form.populateSeasons(seasonDropdown, null, data); + await Form.populateSports(sportDropdown, null, data); + await Form.populateGenders(genderDropdown, null, data); + await Form.populateDivisions(divisionDropdown, null, null, null, data); + await Form.populateTeams(teamDropdown, null, null, data); + + /*let latestGame; try { latestGame = await Data.getLatestGame(); @@ -39,7 +47,7 @@ async function initializeForm() { await Form.populateGenders(genderDropdown, sportDropdown.value); await Form.populateDivisions(divisionDropdown, sportDropdown.value, genderDropdown.value); await Form.populateTeams(teamDropdown, sportDropdown.value); - } + }*/ seasonDropdown.onchange = loadTable; diff --git a/routes/fetch.js b/routes/fetch.js new file mode 100644 index 0000000..756c6df --- /dev/null +++ b/routes/fetch.js @@ -0,0 +1,60 @@ +var express = require('express'); +var router = express.Router(); + +var sports = require('../database/scores/sports'); +var seasons = require('../database/scores/seasons'); +var genders = require('../database/scores/genders'); +var divisions = require('../database/scores/divisions'); +var teams = require('../database/scores/teams'); +var games = require('../database/scores/games'); +var accounts = require('../database/accounts/accounts'); + +var checkLoginStatus = require('./checkLoginStatus'); + +router.get('/index/dropdown', async function(req, res, next) { + let latestGame; + let seasonsData; + let sportsData; + let gendersData; + let divisionsData; + let teamsData; + + try { + latestGame = await games.getLatest(); + } catch { + latestGame = null; + } + + + try { + if(latestGame) { + let division = await divisions.getFromID(latestGame.divisionID); + + seasonsData = await seasons.retrieveAll(); + sportsData = await sports.retrieveAll(); + gendersData = await genders.retrieveBySport(division.sportID); + divisionsData = await divisions.retrieve(division.sportID); + teamsData = await teams.retrieve(division.sportID); + } else { + seasonsData = await seasons.retrieveAll(); + sportsData = await sports.retrieveAll(); + gendersData = await genders.retrieveBySport(sportsData[0].id); + divisionsData = await divisions.retrieve(sportsData[0].id); + teamsData = await teams.retrieve(sportsData[0].id); + } + + res.json({ + seasons : seasonsData, + sports : sportsData, + genders : gendersData, + divisons : divisionsData, + teams: teamsData, + latestGame + }); + } catch(err) { + console.error("ERROR: " + err.message); + res.status(500).send("An error has occurred"); + } +}); + +module.exports = router; \ No newline at end of file From 1e78e379135d1148699eff68eecbcd8aded0384f Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Mon, 7 Mar 2022 12:27:10 -0700 Subject: [PATCH 03/21] Add sports to single request --- public/scripts/form.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/public/scripts/form.js b/public/scripts/form.js index 96dadc6..a693463 100644 --- a/public/scripts/form.js +++ b/public/scripts/form.js @@ -1,9 +1,14 @@ import * as Data from "./data.js"; -export async function populateSports(sportDropdown, selectedSportID = undefined) { +export async function populateSports(sportDropdown, selectedSportID = undefined, data = undefined) { sportDropdown.innerHTML = ""; - const sportsList = await Data.getSports(); + let sportsList; + if(data) { + sportsList = data.sports; + } else { + sportsList = await Data.getSports(); + } let currentIndex = 0; let selectedSportIndex; @@ -13,7 +18,7 @@ export async function populateSports(sportDropdown, selectedSportID = undefined) option.value = sport.id; sportDropdown.appendChild(option); - if(sport.id == selectedSportID) selectedSportIndex = currentIndex; + if(sport.id == selectedSportID || (data && sport.id == data.latestGame.sportID)) selectedSportIndex = currentIndex; currentIndex++; }); @@ -30,7 +35,7 @@ export async function populateSeasons(seasonDropdown, selectedSeasonID = undefin } else { seasonsList = await Data.getSeasons(); } - console.log(data); + let currentIndex = 0; let selectedSeasonIndex; seasonsList.forEach(season => { From b2f66b3e34be7a6b4c3658843afc2548c4cd3cf7 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Mon, 7 Mar 2022 21:31:04 -0700 Subject: [PATCH 04/21] Populate all dropdowns in a single AJAX request --- public/scripts/form.js | 45 ++++++++++++++++++++++++++++++++--------- public/scripts/index.js | 26 +----------------------- routes/fetch.js | 14 +++++++------ 3 files changed, 44 insertions(+), 41 deletions(-) diff --git a/public/scripts/form.js b/public/scripts/form.js index a693463..59e2e3d 100644 --- a/public/scripts/form.js +++ b/public/scripts/form.js @@ -51,11 +51,17 @@ export async function populateSeasons(seasonDropdown, selectedSeasonID = undefin if(selectedSeasonIndex) seasonDropdown.selectedIndex = selectedSeasonIndex; } -export async function populateGenders(genderDropdown, selectedSportID, selectedGender = undefined) { +export async function populateGenders(genderDropdown, selectedSportID, selectedGender = undefined, data = undefined) { genderDropdown.innerHTML = ""; - const gendersList = await Data.getGenders(selectedSportID); - + let gendersList; + if(data) { + gendersList = data.genders; + selectedSportID = data.latestGame.sportID; + } else { + gendersList = await Data.getGenders(selectedSportID); + } + if(selectedSportID) { let currentIndex = 0; let selectedGenderIndex; @@ -65,7 +71,7 @@ export async function populateGenders(genderDropdown, selectedSportID, selectedG option.value = gender.name; genderDropdown.appendChild(option); - if(gender.name == selectedGender) selectedGenderIndex = currentIndex; + if(gender.name == selectedGender || (data && gender.name == data.latestGame.gender.name)) selectedGenderIndex = currentIndex; currentIndex++; }); @@ -73,11 +79,21 @@ export async function populateGenders(genderDropdown, selectedSportID, selectedG } } -export async function populateDivisions (divisionDropdown, selectedSportID, selectedGender, selectedDivisionID = undefined) { +export async function populateDivisions (divisionDropdown, selectedSportID, selectedGender, selectedDivisionID = undefined, data = undefined) { divisionDropdown.innerHTML = ""; + if(data) { + selectedSportID = data.latestGame.sportID; + selectedGender = data.latestGame.gender; + } if(selectedSportID && selectedGender) { - const divisionsList = await Data.getDivisions(selectedSportID, selectedGender); + let divisionsList; + + if(data) { + divisionsList = data.divisions; + } else { + divisionsList = await Data.getDivisions(selectedSportID, selectedGender); + } let currentIndex = 0; let selectedDivisionIndex; @@ -87,7 +103,7 @@ export async function populateDivisions (divisionDropdown, selectedSportID, sele option.value = division.id; divisionDropdown.appendChild(option); - if(division.id == selectedDivisionID) selectedDivisionIndex = currentIndex; + if(division.id == selectedDivisionID || (data && division.id == data.latestGame.divisionID)) selectedDivisionIndex = currentIndex; currentIndex++; }); @@ -95,11 +111,20 @@ export async function populateDivisions (divisionDropdown, selectedSportID, sele } } -export async function populateTeams(teamDropdown, selectedSportID, selectedTeamID = undefined) { +export async function populateTeams(teamDropdown, selectedSportID, selectedTeamID = undefined, data = undefined) { teamDropdown.innerHTML = ""; + if(data) { + selectedSportID = data.latestGame.sportID; + } + if(selectedSportID) { - const teamsList = await Data.getTeams(selectedSportID); + let teamsList; + if(data) { + teamsList = data.teams; + } else { + teamsList = await Data.getTeams(selectedSportID); + } let currentIndex = 0; let selectedTeamIndex; @@ -109,7 +134,7 @@ export async function populateTeams(teamDropdown, selectedSportID, selectedTeamI option.value = team.id; teamDropdown.appendChild(option); - if(team.id == selectedTeamID) selectedTeamIndex = currentIndex; + if(team.id == selectedTeamID || (data && team.id == data.latestGame.team1ID)) selectedTeamIndex = currentIndex; currentIndex++; }); diff --git a/public/scripts/index.js b/public/scripts/index.js index a30d681..ae7bd01 100644 --- a/public/scripts/index.js +++ b/public/scripts/index.js @@ -21,33 +21,9 @@ async function initializeForm() { await Form.populateSeasons(seasonDropdown, null, data); await Form.populateSports(sportDropdown, null, data); - await Form.populateGenders(genderDropdown, null, data); + await Form.populateGenders(genderDropdown, null, null, data); await Form.populateDivisions(divisionDropdown, null, null, null, data); await Form.populateTeams(teamDropdown, null, null, data); - - /*let latestGame; - - try { - latestGame = await Data.getLatestGame(); - } catch { - latestGame = null; - } - - if(latestGame) { - Form.populateSeasons(seasonDropdown, latestGame.seasonID); - - const division = await Data.getDivision(latestGame.divisionID); - await Form.populateSports(sportDropdown, division.sportID); - await Form.populateGenders(genderDropdown, sportDropdown.value, division.gender.name); - await Form.populateDivisions(divisionDropdown, sportDropdown.value, genderDropdown.value, latestGame.divisionID); - await Form.populateTeams(teamDropdown, sportDropdown.value, latestGame.team1ID); - } else { - Form.populateSeasons(seasonDropdown); - await Form.populateSports(sportDropdown); - await Form.populateGenders(genderDropdown, sportDropdown.value); - await Form.populateDivisions(divisionDropdown, sportDropdown.value, genderDropdown.value); - await Form.populateTeams(teamDropdown, sportDropdown.value); - }*/ seasonDropdown.onchange = loadTable; diff --git a/routes/fetch.js b/routes/fetch.js index 756c6df..cbe203a 100644 --- a/routes/fetch.js +++ b/routes/fetch.js @@ -21,6 +21,10 @@ router.get('/index/dropdown', async function(req, res, next) { try { latestGame = await games.getLatest(); + + let division = await divisions.getFromID(latestGame.divisionID); + latestGame.sportID = division.sportID; + latestGame.gender = division.gender; } catch { latestGame = null; } @@ -28,13 +32,11 @@ router.get('/index/dropdown', async function(req, res, next) { try { if(latestGame) { - let division = await divisions.getFromID(latestGame.divisionID); - seasonsData = await seasons.retrieveAll(); sportsData = await sports.retrieveAll(); - gendersData = await genders.retrieveBySport(division.sportID); - divisionsData = await divisions.retrieve(division.sportID); - teamsData = await teams.retrieve(division.sportID); + gendersData = await genders.retrieveBySport(latestGame.sportID); + divisionsData = await divisions.retrieve(latestGame.sportID); + teamsData = await teams.retrieve(latestGame.sportID); } else { seasonsData = await seasons.retrieveAll(); sportsData = await sports.retrieveAll(); @@ -47,7 +49,7 @@ router.get('/index/dropdown', async function(req, res, next) { seasons : seasonsData, sports : sportsData, genders : gendersData, - divisons : divisionsData, + divisions : divisionsData, teams: teamsData, latestGame }); From 36de9b37734c66275a91d7a567acde4f60bc4a59 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Mon, 7 Mar 2022 23:07:26 -0700 Subject: [PATCH 05/21] Speed up loading for home page --- public/scripts/index.js | 6 +++--- routes/fetch.js | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/public/scripts/index.js b/public/scripts/index.js index ae7bd01..3d77b89 100644 --- a/public/scripts/index.js +++ b/public/scripts/index.js @@ -60,7 +60,8 @@ async function loadTable() { if(selectedTeamID && selectedDivisionID) { gamesTableHeader.textContent = `Scores for ${teamDropdown.options[teamDropdown.selectedIndex].text}`; - const gamesList = await Data.getGames(selectedTeamID, selectedDivisionID, selectedSeasonID); + const requestURL = `/fetch/index/scores?team=${+selectedTeamID}&division=${+selectedDivisionID}&season=${+selectedSeasonID}`; + const gamesList = await (await fetch(requestURL)).json(); if(gamesList.length > 0) { await setupGamesTableHeaders(); @@ -77,8 +78,7 @@ async function loadTable() { row.appendChild(scoreCell); const opponentCell = document.createElement('td'); - Data.getTeam(game.team2ID) - .then(data => opponentCell.textContent = data.name); + opponentCell.textContent = game.opponent.name; row.appendChild(opponentCell); const dateCell = document.createElement('td'); diff --git a/routes/fetch.js b/routes/fetch.js index cbe203a..5abc17d 100644 --- a/routes/fetch.js +++ b/routes/fetch.js @@ -59,4 +59,20 @@ router.get('/index/dropdown', async function(req, res, next) { } }); +router.get('/index/scores', async function (req, res, next) { + try { + const seasonID = req.query.season; + const divisionID = req.query.division; + const teamID = req.query.team; + const data = await games.retrieve(teamID, divisionID, seasonID); + for (const game of data) { + game.opponent = await teams.getFromID(game.team2ID); + } + res.json(data); + } catch(err) { + console.error("ERROR: " + err.message); + res.status(500).send("An error has occurred"); + } +}); + module.exports = router; \ No newline at end of file From 9ea7162a0c6d91cb0df4901fc2950957f08bf8c9 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Mon, 7 Mar 2022 23:19:07 -0700 Subject: [PATCH 06/21] Add loading scores message --- public/scripts/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/public/scripts/index.js b/public/scripts/index.js index 3d77b89..6813bba 100644 --- a/public/scripts/index.js +++ b/public/scripts/index.js @@ -59,9 +59,11 @@ async function loadTable() { if(selectedTeamID && selectedDivisionID) { gamesTableHeader.textContent = `Scores for ${teamDropdown.options[teamDropdown.selectedIndex].text}`; - + + noScoresMessage.textContent = "Loading scores..."; const requestURL = `/fetch/index/scores?team=${+selectedTeamID}&division=${+selectedDivisionID}&season=${+selectedSeasonID}`; const gamesList = await (await fetch(requestURL)).json(); + noScoresMessage.textContent = ""; if(gamesList.length > 0) { await setupGamesTableHeaders(); From 703c8bfc5b642e06267610149c981f05ea7c3572 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Tue, 8 Mar 2022 10:38:28 -0700 Subject: [PATCH 07/21] Add loading screen for index --- public/scripts/index.js | 5 +++++ public/stylesheets/index.css | 4 ++++ views/index.pug | 3 ++- 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/public/scripts/index.js b/public/scripts/index.js index 6813bba..de182c7 100644 --- a/public/scripts/index.js +++ b/public/scripts/index.js @@ -1,6 +1,7 @@ import * as Data from "./data.js"; import * as Form from "./form.js"; +const dropdownsDiv = document.getElementById('dropdowns-div'); const sportDropdown = document.getElementById('sport-dropdown'); const seasonDropdown = document.getElementById('year-dropdown'); const genderDropdown = document.getElementById('gender-dropdown'); @@ -11,6 +12,7 @@ const gamesTableHeader = document.getElementById('games-table-header'); const noScoresMessage = document.getElementById('no-scores-message'); const addScoreButton = document.getElementById('add-score-button'); const manageButton = document.getElementById('manage-button'); +const loadingSpan = document.getElementById('loading'); @@ -42,6 +44,9 @@ async function initializeForm() { divisionDropdown.onchange = loadTable; teamDropdown.onchange = loadTable; + loadingSpan.textContent = ''; + dropdownsDiv.style.visibility = 'visible'; + loadTable(); diff --git a/public/stylesheets/index.css b/public/stylesheets/index.css index eb71b13..bf0a4ae 100644 --- a/public/stylesheets/index.css +++ b/public/stylesheets/index.css @@ -32,3 +32,7 @@ tr { #login-button { margin-left: auto; } + +#dropdowns-div { + visibility: hidden; +} \ No newline at end of file diff --git a/views/index.pug b/views/index.pug index a1b7d2d..1a22bbe 100644 --- a/views/index.pug +++ b/views/index.pug @@ -11,7 +11,8 @@ block actions block content - div + span#loading Loading... + div#dropdowns-div span(class='form-section') label Year span(class='form-section-input') From 7ec36ed7f24a5554150b92e72bc9d7d6305a28a7 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Tue, 8 Mar 2022 10:55:23 -0700 Subject: [PATCH 08/21] Fine tune loading for submit page --- public/scripts/form.js | 9 +++++-- public/scripts/manage/game.js | 25 +++++++++-------- public/stylesheets/form.css | 6 ++++- routes/fetch.js | 51 +++++++++++++++++++++++++++++++++++ views/manage/addgame.pug | 1 + 5 files changed, 78 insertions(+), 14 deletions(-) diff --git a/public/scripts/form.js b/public/scripts/form.js index 59e2e3d..acc3eaa 100644 --- a/public/scripts/form.js +++ b/public/scripts/form.js @@ -111,7 +111,7 @@ export async function populateDivisions (divisionDropdown, selectedSportID, sele } } -export async function populateTeams(teamDropdown, selectedSportID, selectedTeamID = undefined, data = undefined) { +export async function populateTeams(teamDropdown, selectedSportID, selectedTeamID = undefined, data = undefined, useOpponent = false) { teamDropdown.innerHTML = ""; if(data) { @@ -128,13 +128,18 @@ export async function populateTeams(teamDropdown, selectedSportID, selectedTeamI let currentIndex = 0; let selectedTeamIndex; + + if(data) { + selectedTeamID = useOpponent ? data.latestGame.team2ID : data.latestGame.team1ID; + } + teamsList.forEach(team => { const option = document.createElement('option'); option.text = team.name; option.value = team.id; teamDropdown.appendChild(option); - if(team.id == selectedTeamID || (data && team.id == data.latestGame.team1ID)) selectedTeamIndex = currentIndex; + if(team.id == selectedTeamID) selectedTeamIndex = currentIndex; currentIndex++; }); diff --git a/public/scripts/manage/game.js b/public/scripts/manage/game.js index 5d0bd29..c61d05b 100644 --- a/public/scripts/manage/game.js +++ b/public/scripts/manage/game.js @@ -15,6 +15,7 @@ const team2ScoreTextbox = document.getElementById('team2-score-textbox'); const nameTextbox = document.getElementById('name-textbox'); const submitButton = document.getElementById('submit-button'); const deleteButton = document.getElementById('delete-button'); +const loadingSpan = document.getElementById('loading-span'); async function initializeForm() { @@ -41,24 +42,23 @@ async function initializeForm() { team2ScoreTextbox.value = game.team2Score; } else { - try { - const game = await Data.getLatestGame(true); + /*try {*/ + const data = await (await fetch(`/fetch/index/dropdown`)).json(); - Form.populateSeasons(seasonDropdown, game.seasonID); - const data = await Data.getDivision(game.divisionID) - await Form.populateSports(sportDropdown, data.sportID) - await Form.populateGenders(genderDropdown, sportDropdown.value, data.gender.name) - await Form.populateDivisions(divisionDropdown, sportDropdown.value, genderDropdown.value, game.divisionID); - await Form.populateTeams(team1Dropdown, sportDropdown.value, game.team1ID); - await Form.populateTeams(team2Dropdown, sportDropdown.value, game.team2ID); - } catch { + await Form.populateSeasons(seasonDropdown, null, data); + await Form.populateSports(sportDropdown, null, data); + await Form.populateGenders(genderDropdown, null, null, data); + await Form.populateDivisions(divisionDropdown, null, null, null, data); + await Form.populateTeams(team1Dropdown, null, null, data); + await Form.populateTeams(team2Dropdown, null, null, data, true); + /*} catch { await Form.populateSeasons(seasonDropdown); await Form.populateSports(sportDropdown) await Form.populateGenders(genderDropdown, sportDropdown.value) await Form.populateDivisions(divisionDropdown, sportDropdown.value, genderDropdown.value); await Form.populateTeams(team1Dropdown, sportDropdown.value); await Form.populateTeams(team2Dropdown, sportDropdown.value); - } + }*/ dateInput.value = (new Date()).toISOString().slice(0,10); } @@ -95,6 +95,9 @@ async function initializeForm() { team2ScoreTextbox.addEventListener('keyup', checkDataValidity); if(nameTextbox) nameTextbox.addEventListener('keyup', checkDataValidity); + loadingSpan.textContent = ''; + submissionForm.style.visibility = 'visible'; + checkDataValidity(); } initializeForm(); diff --git a/public/stylesheets/form.css b/public/stylesheets/form.css index 43fee2e..c040b27 100644 --- a/public/stylesheets/form.css +++ b/public/stylesheets/form.css @@ -48,4 +48,8 @@ form { .flat-form-section { flex-direction: row; - } \ No newline at end of file + } + +#submission-form { + visibility: hidden; +} \ No newline at end of file diff --git a/routes/fetch.js b/routes/fetch.js index 5abc17d..fddaefe 100644 --- a/routes/fetch.js +++ b/routes/fetch.js @@ -75,4 +75,55 @@ router.get('/index/scores', async function (req, res, next) { } }); + +router.get('/submit', async function(req, res, next) { + let latestGame; + let seasonsData; + let sportsData; + let gendersData; + let divisionsData; + let teamsData; + + const userID = req.user ? req.user[0] : null; + + try { + latestGame = await games.getLatest(userID); + + let division = await divisions.getFromID(latestGame.divisionID); + latestGame.sportID = division.sportID; + latestGame.gender = division.gender; + } catch { + latestGame = null; + } + + + try { + if(latestGame) { + seasonsData = await seasons.retrieveAll(); + sportsData = await sports.retrieveAll(); + gendersData = await genders.retrieveBySport(latestGame.sportID); + divisionsData = await divisions.retrieve(latestGame.sportID); + teamsData = await teams.retrieve(latestGame.sportID); + } else { + seasonsData = await seasons.retrieveAll(); + sportsData = await sports.retrieveAll(); + gendersData = await genders.retrieveBySport(sportsData[0].id); + divisionsData = await divisions.retrieve(sportsData[0].id); + teamsData = await teams.retrieve(sportsData[0].id); + } + + res.json({ + seasons : seasonsData, + sports : sportsData, + genders : gendersData, + divisions : divisionsData, + teams: teamsData, + latestGame + }); + } catch(err) { + console.error("ERROR: " + err.message); + res.status(500).send("An error has occurred"); + } +}); + module.exports = router; \ No newline at end of file diff --git a/views/manage/addgame.pug b/views/manage/addgame.pug index bdc362c..dc56f5d 100644 --- a/views/manage/addgame.pug +++ b/views/manage/addgame.pug @@ -5,6 +5,7 @@ block stylesheets link(rel='stylesheet', href='/stylesheets/form.css') block content + span#loading-span Loading... form#submission-form(action='./game', method='POST') span(class='form-section') label Year From 42ac77ec6ffcf0983a34c66fe940cf80a275dc15 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Wed, 9 Mar 2022 10:20:53 -0700 Subject: [PATCH 09/21] Add loading message to manage page --- public/scripts/manage.js | 5 +++++ views/manage.pug | 1 + 2 files changed, 6 insertions(+) diff --git a/public/scripts/manage.js b/public/scripts/manage.js index a77a7d6..04ebb1c 100644 --- a/public/scripts/manage.js +++ b/public/scripts/manage.js @@ -3,6 +3,7 @@ import * as Data from "./data.js"; const categoryDropdown = document.getElementById('category-dropdown'); const itemsListTable = document.getElementById('items-list'); const addNewButton = document.getElementById('add-new-button'); +const loadingSpan = document.getElementById('loading-message'); function getGenderLetter(genderName) { @@ -362,6 +363,8 @@ CATEGORIES.push(new Category( async function listItems(category) { + loadingSpan.textContent = "Loading..."; + itemsListTable.innerHTML = ""; const itemsList = await category.getItems(); @@ -389,6 +392,8 @@ async function listItems(category) { itemsListTable.appendChild(row); }); + + loadingSpan.textContent = ''; } if(window.location.hash) { let correctIndex; diff --git a/views/manage.pug b/views/manage.pug index 63d76ec..bd8a228 100644 --- a/views/manage.pug +++ b/views/manage.pug @@ -18,6 +18,7 @@ block content option(value="accounts") Accounts div h2#table-header + span#loading-message Loading... table#items-list button#add-new-button Add new... From 18628e3fe5326ce3fb22bcc086a11be4e4591b5d Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Wed, 9 Mar 2022 10:28:28 -0700 Subject: [PATCH 10/21] Speed up loading divisions on manage page --- public/scripts/manage.js | 6 +++--- routes/fetch.js | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/public/scripts/manage.js b/public/scripts/manage.js index 04ebb1c..a96bac9 100644 --- a/public/scripts/manage.js +++ b/public/scripts/manage.js @@ -115,7 +115,7 @@ CATEGORIES.push(new Category( CATEGORIES.push(new Category( "divisions", async function getDivisions() { - return await Data.getDivisions(); + return await (await fetch('/fetch/manage/divisions')).json(); }, async function listDivisionHeaders() { const headerRow = document.createElement('tr'); @@ -151,8 +151,8 @@ CATEGORIES.push(new Category( row.appendChild(spacerCell); const sportCell = document.createElement('td'); - Data.getSportName(division.sportID) - .then(data => sportCell.textContent = data); + let sportName = division.sport.name; + sportCell.textContent = sportName; row.appendChild(sportCell); }, async function addDivision() { diff --git a/routes/fetch.js b/routes/fetch.js index fddaefe..28a98ea 100644 --- a/routes/fetch.js +++ b/routes/fetch.js @@ -126,4 +126,14 @@ router.get('/submit', async function(req, res, next) { } }); +router.get('/manage/divisions', async function (req, res, next) { + const data = await divisions.retrieve(); + + for(const division of data) { + division.sport = await sports.getFromID(division.sportID); + } + + res.json(data); +}); + module.exports = router; \ No newline at end of file From 05473e07ad4949504a1abbfe116cd75e228dee07 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Wed, 9 Mar 2022 10:32:47 -0700 Subject: [PATCH 11/21] Speed up loading teams --- public/scripts/manage.js | 6 +++--- routes/fetch.js | 10 ++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/public/scripts/manage.js b/public/scripts/manage.js index a96bac9..6fc6b07 100644 --- a/public/scripts/manage.js +++ b/public/scripts/manage.js @@ -166,7 +166,7 @@ CATEGORIES.push(new Category( CATEGORIES.push(new Category( "teams", async function getTeams() { - return await Data.getTeams(); + return await (await fetch('/fetch/manage/teams')).json(); }, async function listTeamHeaders() { const headerRow = document.createElement('tr'); @@ -194,8 +194,8 @@ CATEGORIES.push(new Category( row.appendChild(spacerCell); const sportCell = document.createElement('td'); - Data.getSportName(team.sportID) - .then(data => sportCell.textContent = data); + let sportName = team.sport.name; + sportCell.textContent = sportName; row.appendChild(sportCell); }, async function addTeam() { diff --git a/routes/fetch.js b/routes/fetch.js index 28a98ea..c140ead 100644 --- a/routes/fetch.js +++ b/routes/fetch.js @@ -136,4 +136,14 @@ router.get('/manage/divisions', async function (req, res, next) { res.json(data); }); +router.get('/manage/teams', async function (req, res, next) { + const data = await teams.retrieve(); + + for(const team of data) { + team.sport = await sports.getFromID(team.sportID); + } + + res.json(data); +}); + module.exports = router; \ No newline at end of file From 55a6fc7d7b1a81fa82ba56f5fda98d6043ce8e95 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Wed, 9 Mar 2022 10:52:02 -0700 Subject: [PATCH 12/21] Improve loading for manage games page --- public/scripts/manage.js | 27 ++++++++++++--------------- routes/fetch.js | 27 +++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/public/scripts/manage.js b/public/scripts/manage.js index 6fc6b07..db29cad 100644 --- a/public/scripts/manage.js +++ b/public/scripts/manage.js @@ -209,7 +209,7 @@ CATEGORIES.push(new Category( CATEGORIES.push(new Category( "games", async function getGames() { - return await Data.getGames(); + return await (await fetch('/fetch/manage/games')).json(); }, async function listGameHeaders() { const headerRow = document.createElement('tr'); @@ -242,12 +242,12 @@ CATEGORIES.push(new Category( function listGame(game, row) { const teamsCell = document.createElement('td'); const team1NameSpan = document.createElement('span'); - Data.getTeam(game.team1ID) - .then(data => team1NameSpan.textContent = data.name); + let team1Name = game.team1.name; + team1NameSpan.textContent = team1Name; teamsCell.appendChild(team1NameSpan); const team2NameSpan = document.createElement('span'); - Data.getTeam(game.team2ID) - .then(data => team2NameSpan.textContent = data.name); + let team2Name = game.team2.name; + team2NameSpan.textContent = team2Name; teamsCell.appendChild(team2NameSpan); row.appendChild(teamsCell); @@ -271,13 +271,11 @@ CATEGORIES.push(new Category( const divisionGenderSpan = document.createElement('span'); divisionSpan.appendChild(divisionNameSpan); divisionSpan.appendChild(divisionGenderSpan); - Data.getDivision(game.divisionID) - .then(data => { - Data.getSportName(data.sportID) - .then(data => sportSpan.textContent = data); - divisionNameSpan.textContent = data.name; - divisionGenderSpan.textContent = getGenderLetter(data.gender.name); - }); + let divisionName = game.division.name; + let sportName = game.sport.name; + divisionNameSpan.textContent = divisionName; + sportSpan.textContent = sportName; + divisionGenderSpan.textContent = getGenderLetter(game.division.gender.name); sportCell.appendChild(sportSpan); sportCell.appendChild(divisionSpan); row.appendChild(sportCell); @@ -293,11 +291,10 @@ CATEGORIES.push(new Category( const submitterCell = document.createElement('td'); if(game.submitterID) { - Data.getAccount(game.submitterID) - .then(data => submitterCell.textContent = data.name); + let submitterName = game.submitter.name; + submitterCell.textContent = submitterName; } else { submitterCell.textContent = game.submitterName; - console.log(game.submitterName); } row.appendChild(submitterCell); }, diff --git a/routes/fetch.js b/routes/fetch.js index c140ead..a8b317e 100644 --- a/routes/fetch.js +++ b/routes/fetch.js @@ -146,4 +146,31 @@ router.get('/manage/teams', async function (req, res, next) { res.json(data); }); +router.get('/manage/games', checkLoginStatus.user, async function (req, res, next) { + try{ + const userIsAdmin = req.user[2]; + const loggedInAccountID = req.user[0]; + + if(!userIsAdmin) { + res.status(403).send("ACCESS DENIED"); + } else { + const data = await games.retrieve(); + + for(const game of data) { + game.team1 = await teams.getFromID(game.team1ID); + game.team2 = await teams.getFromID(game.team2ID); + game.division = await divisions.getFromID(game.divisionID); + game.sport = await sports.getFromID(game.division.sportID); + game.submitter = game.submitterName || (await accounts.getFromID(game.submitterID)); + } + + res.json(data); + } + } catch(err) { + console.error("ERROR: " + err.message); + res.status(500).send("An error has occurred"); + } + +}); + module.exports = router; \ No newline at end of file From 5adf9274128feb6960278b1c0a64b755896413b8 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Wed, 9 Mar 2022 10:54:50 -0700 Subject: [PATCH 13/21] Make submission form visible for sport edit page --- public/scripts/manage/sport.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/public/scripts/manage/sport.js b/public/scripts/manage/sport.js index 20ad2cb..7ab54e7 100644 --- a/public/scripts/manage/sport.js +++ b/public/scripts/manage/sport.js @@ -26,6 +26,8 @@ async function initializeForm() { nameTextbox.disabled = false; nameTextbox.addEventListener('keyup', checkDataValidity); + + submissionForm.style.visibility = 'visible'; } initializeForm(); From 492d10f6359098d148bae5a890e18018f9d65681 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Wed, 9 Mar 2022 10:56:35 -0700 Subject: [PATCH 14/21] Add loading message to sport submit form --- public/scripts/manage/sport.js | 2 ++ views/manage/addsport.pug | 1 + 2 files changed, 3 insertions(+) diff --git a/public/scripts/manage/sport.js b/public/scripts/manage/sport.js index 7ab54e7..b44b41a 100644 --- a/public/scripts/manage/sport.js +++ b/public/scripts/manage/sport.js @@ -5,6 +5,7 @@ const nameTextbox = document.getElementById('name-textbox'); const submitButton = document.getElementById('submit-button'); const deleteButton = document.getElementById('delete-button'); const submissionForm = document.getElementById('submission-form'); +const loadingSpan = document.getElementById('loading-message'); async function initializeForm() { @@ -27,6 +28,7 @@ async function initializeForm() { nameTextbox.addEventListener('keyup', checkDataValidity); + loadingSpan.textContent = ''; submissionForm.style.visibility = 'visible'; } initializeForm(); diff --git a/views/manage/addsport.pug b/views/manage/addsport.pug index b4caa50..6530488 100644 --- a/views/manage/addsport.pug +++ b/views/manage/addsport.pug @@ -5,6 +5,7 @@ block stylesheets link(rel='stylesheet', href='/stylesheets/form.css') block content + span#loading-message Loading... form#submission-form(action='./sport', method='POST') span(class='form-section') label Sport name From ee6353f013950e434e5e20655ca18f02fcc72682 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Wed, 9 Mar 2022 11:00:17 -0700 Subject: [PATCH 15/21] Add loading message to division --- public/scripts/manage/division.js | 4 ++++ views/manage/adddivision.pug | 1 + 2 files changed, 5 insertions(+) diff --git a/public/scripts/manage/division.js b/public/scripts/manage/division.js index a542a65..1d75742 100644 --- a/public/scripts/manage/division.js +++ b/public/scripts/manage/division.js @@ -8,6 +8,7 @@ const genderDropdown = document.getElementById('gender-dropdown'); const nameTextbox = document.getElementById('name-textbox'); const submitButton = document.getElementById('submit-button'); const deleteButton = document.getElementById('delete-button'); +const loadingSpan = document.getElementById('loading-message'); async function initializeForm() { @@ -40,6 +41,9 @@ async function initializeForm() { nameTextbox.disabled = false; nameTextbox.addEventListener('keyup', checkDataValidity); + + loadingSpan.textContent = ''; + submissionForm.style.visibility = 'visible'; } initializeForm(); diff --git a/views/manage/adddivision.pug b/views/manage/adddivision.pug index 1a17aaf..3471bc5 100644 --- a/views/manage/adddivision.pug +++ b/views/manage/adddivision.pug @@ -5,6 +5,7 @@ block stylesheets link(rel='stylesheet', href='/stylesheets/form.css') block content + span#loading-message Loading... form#submission-form(action='./division', method='POST') span(class='form-section') label Sport From 59e671e1ec6c5448b8cd43a338a795623d7ece0a Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Wed, 9 Mar 2022 11:00:27 -0700 Subject: [PATCH 16/21] Add loading message to team management --- public/scripts/manage/team.js | 5 +++++ views/manage/addteam.pug | 1 + 2 files changed, 6 insertions(+) diff --git a/public/scripts/manage/team.js b/public/scripts/manage/team.js index 4bc643e..cd5ac95 100644 --- a/public/scripts/manage/team.js +++ b/public/scripts/manage/team.js @@ -7,6 +7,8 @@ const sportDropdown = document.getElementById('sport-dropdown'); const nameTextbox = document.getElementById('name-textbox'); const submitButton = document.getElementById('submit-button'); const deleteButton = document.getElementById('delete-button'); +const loadingSpan = document.getElementById('loading-message'); + async function initializeForm() { let params = new URLSearchParams(location.search); @@ -31,6 +33,9 @@ async function initializeForm() { nameTextbox.disabled = false; nameTextbox.addEventListener('keyup', checkDataValidity); + + loadingSpan.textContent = ''; + submissionForm.style.visibility = 'visible'; } initializeForm(); diff --git a/views/manage/addteam.pug b/views/manage/addteam.pug index 78746a6..17d42d3 100644 --- a/views/manage/addteam.pug +++ b/views/manage/addteam.pug @@ -5,6 +5,7 @@ block stylesheets link(rel='stylesheet', href='/stylesheets/form.css') block content + span#loading-message Loading... form#submission-form(action='./team', method='POST') span(class='form-section') label Sport From 3a54ce0d561e4169b4ce76a1ce2a8318133eb811 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Wed, 9 Mar 2022 11:02:00 -0700 Subject: [PATCH 17/21] Improve loading for account editing --- public/scripts/manage/account.js | 4 ++++ views/accounts/createuser.pug | 1 + 2 files changed, 5 insertions(+) diff --git a/public/scripts/manage/account.js b/public/scripts/manage/account.js index f9a7370..3e14638 100644 --- a/public/scripts/manage/account.js +++ b/public/scripts/manage/account.js @@ -9,6 +9,7 @@ const adminCheckboxSection = document.getElementById('admin-checkbox-section'); const adminCheckbox = document.getElementById('admin-checkbox'); const submitButton = document.getElementById('submit-button'); const deleteButton = document.getElementById('delete-button'); +const loadingSpan = document.getElementById('loading-message'); async function Initialize() { let params = new URLSearchParams(location.search); @@ -46,6 +47,9 @@ async function Initialize() { passwordTextbox.disabled = false; passwordTextbox.addEventListener('keyup', checkDataValidity); checkDataValidity(); + + loadingSpan.textContent = ''; + submissionForm.style.visibility = 'visible'; } Initialize(); diff --git a/views/accounts/createuser.pug b/views/accounts/createuser.pug index b0c0ca2..a43aad9 100644 --- a/views/accounts/createuser.pug +++ b/views/accounts/createuser.pug @@ -5,6 +5,7 @@ block stylesheets link(rel='stylesheet', href='/stylesheets/form.css') block content + span#loading-message Loading... form#submission-form(action='/manage/account', method='POST') if accountID input#account-id(type="hidden" name="account" value=accountID) From 29605613c0461c1b9dc83a90daf5023a313bcef3 Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Wed, 9 Mar 2022 16:55:07 -0700 Subject: [PATCH 18/21] Improve loading for editing divisions --- public/scripts/manage/division.js | 8 ++++++-- routes/fetch.js | 12 ++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/public/scripts/manage/division.js b/public/scripts/manage/division.js index 1d75742..8474b4b 100644 --- a/public/scripts/manage/division.js +++ b/public/scripts/manage/division.js @@ -15,7 +15,7 @@ async function initializeForm() { let params = new URLSearchParams(location.search); let divisionID = params.get('division'); if(divisionID) { - const division = await Data.getDivision(divisionID); + const division = await (await fetch(`/fetch/manage/division?division=${divisionID}`)).json(); nameTextbox.value = division.name; @@ -27,7 +27,11 @@ async function initializeForm() { if(gender == 'female') genderDropdown.selectedIndex = 1; else genderDropdown.selectedIndex = 2; - Form.populateSports(sportDropdown, division.sportID); + let data = {}; + data.sports = [division.sport]; + data.latestGame = {sportID : division.sportID }; + + Form.populateSports(sportDropdown, null, data); Form.addHiddenValue('division', divisionID, submissionForm); } diff --git a/routes/fetch.js b/routes/fetch.js index a8b317e..f807190 100644 --- a/routes/fetch.js +++ b/routes/fetch.js @@ -136,6 +136,18 @@ router.get('/manage/divisions', async function (req, res, next) { res.json(data); }); +router.get('/manage/division', async function (req, res, next) { + try { + const divisionID = req.query.division; + const data = await divisions.getFromID(divisionID); + data.sport = await sports.getFromID(data.sportID); + res.json(data); + } catch(err) { + console.error("ERROR: " + err.message); + res.status(500).send("An error has occurred"); + } +}); + router.get('/manage/teams', async function (req, res, next) { const data = await teams.retrieve(); From 8d830735fffa6e3363afb3b674830ad8146dfb6f Mon Sep 17 00:00:00 2001 From: sudoer777 <78781902+sudoer777@users.noreply.github.com> Date: Wed, 9 Mar 2022 17:57:18 -0700 Subject: [PATCH 19/21] Add better loading for editing teams --- public/scripts/manage/team.js | 8 ++++++-- routes/data.js | 2 +- routes/fetch.js | 12 ++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/public/scripts/manage/team.js b/public/scripts/manage/team.js index cd5ac95..a7eadce 100644 --- a/public/scripts/manage/team.js +++ b/public/scripts/manage/team.js @@ -14,14 +14,18 @@ async function initializeForm() { let params = new URLSearchParams(location.search); let teamID = params.get('team'); if(teamID) { - const team = await Data.getTeam(teamID); + const team = await (await fetch(`/fetch/manage/team?team=${teamID}`)).json(); nameTextbox.value = team.name; deleteButton.style.visibility = "visible"; deleteButton.disabled = false; - Form.populateSports(sportDropdown, team.sportID); + let data = {}; + data.sports = [team.sport]; + data.latestGame = {sportID : team.sportID }; + + Form.populateSports(sportDropdown, null, data); Form.addHiddenValue('team', teamID, submissionForm); } diff --git a/routes/data.js b/routes/data.js index b6769d5..55c1970 100644 --- a/routes/data.js +++ b/routes/data.js @@ -98,7 +98,7 @@ router.get('/team', async function(req, res, next) { console.error("ERROR: " + err.message); res.status(500).send("An error has occurred"); } -}) +}); router.get('/games', async function(req, res, next) { try { diff --git a/routes/fetch.js b/routes/fetch.js index f807190..4958fd3 100644 --- a/routes/fetch.js +++ b/routes/fetch.js @@ -158,6 +158,18 @@ router.get('/manage/teams', async function (req, res, next) { res.json(data); }); +router.get('/manage/team', async function (req, res, next) { + try { + const teamID = req.query.team; + const data = await teams.getFromID(teamID); + data.sport = await sports.getFromID(data.sportID); + res.json(data); + } catch(err) { + console.error("ERROR: " + err.message); + res.status(500).send("An error has occurred"); + } +}); + router.get('/manage/games', checkLoginStatus.user, async function (req, res, next) { try{ const userIsAdmin = req.user[2]; From 6ceeed1ef6a853894a7425905746fbcd66883aae Mon Sep 17 00:00:00 2001 From: Sudoer777 Date: Thu, 10 Mar 2022 01:08:05 +0000 Subject: [PATCH 20/21] Update README.md --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3835188..6d558c8 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,11 @@ A web app designed to collect and display scores for sports ## Installation -This repository is designed to be pushed to Heroku/Dokku/etc. +This repository can be cloned and then pushed to Heroku/Dokku/etc. ### Requirements -- PostgreSQL (with empty database created and an account to access it) +- PostgreSQL (with an empty database created and an account to access it) ### Environment Variables @@ -32,6 +32,8 @@ This repository is designed to be pushed to Heroku/Dokku/etc. This program uses Node.js/Express.js for the backend, PostgreSQL for the database (with node-postgres), and Passport.js for managing users and sessions. +To view the code, clone the repository and open it in VSCode/VSCodium. + ### Structure - `database` folder contains backend scripts for managing and storing data. @@ -44,6 +46,7 @@ This program uses Node.js/Express.js for the backend, PostgreSQL for the databas - `auth.js` deals with logging in and out (`/auth/*`). - `checkLoginStatus.js` contains functions for checking the login status of the current user. - `data.js` sends various data to the client in JSON format (`/data/*`). + - `fetch.js` sends more specific data formatted for specific pages in JSON format (`/fetch/*`) - `index.js` directs to the home page (`/`). - `manage.js` contains various functions that allows the user to add and edit items through the web browser (`/manage/*`). - `views` folder contains pug templates for each webpage, and a `layout` template for the base layout of each page. From 946316d4b53b6bd5f104c22d4bb130c693acbe80 Mon Sep 17 00:00:00 2001 From: Sudoer777 Date: Thu, 10 Mar 2022 01:15:32 +0000 Subject: [PATCH 21/21] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b504c93..2e017a4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "score-tracker", - "version": "1.0.3-pre", + "version": "1.2.0", "private": true, "scripts": { "start": "node ./bin/www"