Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement environment variables #99

Merged
merged 29 commits into from
Dec 31, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
56de767
Add game title env var
karlromets Dec 27, 2024
586dfd1
Add max file upload env vars
karlromets Dec 27, 2024
29003ce
Fix improper settimeout
karlromets Dec 27, 2024
e0db5e2
Improve file type validation for CSV and JSON uploads
karlromets Dec 27, 2024
c8cf2b3
Add prettier config
karlromets Dec 28, 2024
48ad10d
merge(master): sync latest changes
karlromets Dec 28, 2024
5a8538a
Title screen styling fixes
karlromets Dec 28, 2024
fcb8302
Refactor Title component to use Team, RoomCode, and TitleUrl components
karlromets Dec 28, 2024
e68f64c
Rename title to TitlePage and move it to Title/
karlromets Dec 28, 2024
b0fefd0
Default to opt out of TITLE_URL
karlromets Dec 28, 2024
24f201f
Return null instead of nothing
karlromets Dec 28, 2024
feefcc8
Update tailwind config
karlromets Dec 28, 2024
eea21cc
merge(master): sync latest changes
karlromets Dec 29, 2024
27e4467
Players in Team now scrollable on overflow
karlromets Dec 29, 2024
0982c4c
Update README.md
karlromets Dec 29, 2024
7990b05
Remove title timeout
karlromets Dec 29, 2024
37aa7e4
Styling changes to title page
karlromets Dec 29, 2024
4c35685
Resolve merge conflicts
karlromets Dec 29, 2024
6b7fa16
chore(conflicts): sync with master branch
karlromets Dec 30, 2024
7224daf
fix(tests): Update team id
karlromets Dec 30, 2024
d32f2fd
chore(deps): add playwright as a dev dependency
karlromets Dec 30, 2024
5a471aa
chore(deps): remove playwright (already exists) & add npm test script
karlromets Dec 30, 2024
d4a5a11
fix(backend): prevent panic/crash on invalid session format
karlromets Dec 30, 2024
495db95
fix(frontend): preserve spectator session format in pong messages
karlromets Dec 30, 2024
e21448a
fix(frontend): ensure final round timer initializes correctly
karlromets Dec 30, 2024
0fb952c
fix(e2e): remove extra quit press
karlromets Dec 30, 2024
dc8ce4f
fix(e2e): improve test reliability with proper timeouts and retries
karlromets Dec 30, 2024
18ef572
fix(backend): align error codes with translation system
karlromets Dec 30, 2024
1c72d0c
fix(backend): use var instead of string
karlromets Dec 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
NEXT_PUBLIC_TITLE_URL='famf.app'
karlromets marked this conversation as resolved.
Show resolved Hide resolved
NEXT_PUBLIC_MAX_IMAGE_UPLOAD_SIZE_MB=2
NEXT_PUBLIC_MAX_CSV_UPLOAD_SIZE_MB=2
karlromets marked this conversation as resolved.
Show resolved Hide resolved
13 changes: 13 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"printWidth": 120,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "es5",
"semi": true,
"singleQuote": true,
"bracketSpacing": true,
"arrowParens": "always",
"jsxSingleQuote": false,
"bracketSameLine": false,
"endOfLine": "lf"
}
92 changes: 56 additions & 36 deletions components/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import LanguageSwitcher from "./language";
import CSVLoader from "./Admin/csv-loader";
import { Buffer } from "buffer";
import { BSON } from "bson";
import { handleCsvFile, handleJsonFile } from "utils/files";

function debounce(callback, wait = 400) {
let timeout;
Expand Down Expand Up @@ -225,9 +226,7 @@ function TitleLogoUpload(props) {
var file = document.getElementById("logoUpload").files[0];

if (file) {
const fileSize = Math.round(file.size / 1024);
// 2MB
if (fileSize > 2098) {
if (file.size > process.env.NEXT_PUBLIC_MAX_IMAGE_UPLOAD_SIZE_MB * 1024 * 1024) {
console.error("Logo image is too large");
props.setError(
t("Logo image is too large. 2MB is the limit"),
Expand Down Expand Up @@ -349,6 +348,18 @@ function FinalRoundPointTotals(props) {
);
}

function isValidFileType(file, allowedTypes) {
const fileName = file.name.toLowerCase();
const fileExtension = fileName.split('.').pop();

if(!allowedTypes[fileExtension]) {
return false;
}

const mimePattern = allowedTypes[fileExtension].pattern;
return mimePattern.test(file.type);
}

export default function Admin(props) {
const { i18n, t } = useTranslation();

Expand Down Expand Up @@ -522,6 +533,7 @@ export default function Admin(props) {
))}
</select>
) : null}
{/* Image Upload */}
<div className="image-upload w-6">
<label htmlFor="gamePicker">
<svg
Expand All @@ -531,48 +543,56 @@ export default function Admin(props) {
<path d="M224 136V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24V160H248c-13.2 0-24-10.8-24-24zm65.18 216.01H224v80c0 8.84-7.16 16-16 16h-32c-8.84 0-16-7.16-16-16v-80H94.82c-14.28 0-21.41-17.29-11.27-27.36l96.42-95.7c6.65-6.61 17.39-6.61 24.04 0l96.42 95.7c10.15 10.07 3.03 27.36-11.25 27.36zM377 105L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1c0-6.3-2.5-12.4-7-16.9z" />
</svg>
</label>
{/* CSV Upload */}
<input
className="hidden"
type="file"
accept=".json, .csv"
id="gamePicker"
onChange={(e) => {
var file = document.getElementById("gamePicker").files[0];
console.debug(file);
if (file?.type === "application/json") {
if (file) {
var reader = new FileReader();
reader.readAsText(file, "utf-8");
reader.onload = function(evt) {
let data = JSON.parse(evt.target.result);
console.debug(data);
// TODO some error checking for invalid game data
send({ action: "load_game", data: data });
};
reader.onerror = function(evt) {
console.error("error reading file");
setError(t("error reading file"));
};

if (file) {
if (file.size > process.env.NEXT_PUBLIC_MAX_CSV_UPLOAD_SIZE_MB * 1024 * 1024) {
console.error("This csv file is too large");
props.setError(
t("This csv file is too large"),
karlromets marked this conversation as resolved.
Show resolved Hide resolved
);
return;
}
} else if (file?.type === "text/csv") {
var reader = new FileReader();
reader.readAsText(file, "utf-8");
reader.onload = function(evt) {
let lineCount = evt.target.result.split("\n");
if (lineCount.length > 30) {
setError(t("This csv file is too large"));
} else {
setCsvFileUpload(file);
setCsvFileUploadText(evt.target.result);
}
};
reader.onerror = function(evt) {
console.error("error reading file");
setError(t("error reading file"));
};
} else {
setError(t("Unknown file type in game load"));
}

const allowedTypes = {
'json': {
pattern: /^application\/(json|.*\+json)$/,
handler: (file) => handleJsonFile(file, {
setError,
t,
send
})
},
'csv': {
pattern: /^(text\/csv|application\/(vnd\.ms-excel|csv|x-csv|text-csv))$/,
handler: (file) => handleCsvFile(file, {
setError,
t,
setCsvFileUpload,
setCsvFileUploadText
})
}
};

const fileType = isValidFileType(file, allowedTypes);
if (!fileType) {
setError(t("Unknown file type"));
return;
}

const fileExtension = file.name.toLowerCase().split('.').pop();
allowedTypes[fileExtension].handler(file);

console.debug(file);

// allow same file to be selected again
document.getElementById("gamePicker").value = null;
}}
Expand Down
30 changes: 25 additions & 5 deletions components/title.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import "tailwindcss/tailwind.css";
import TitleLogo from "./title-logo";
import { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";

export default function Title(props) {
const {i18n, t} = useTranslation();
const [titleSize, setTitleSize] = useState("10%");

useEffect(() => {
if (props.game.settings.logo_url) {
setTimeout(setTitleSize(window.innerWidth * 0.4), 2000);
setTimeout(() => setTitleSize(window.innerWidth * 0.4), 2000);
} else {
setTimeout(setTitleSize(window.innerWidth * 0.7), 2000);
setTimeout(() => setTitleSize(window.innerWidth * 0.7), 2000);
}
}, []);

Expand All @@ -35,6 +37,7 @@ export default function Title(props) {
}}
className="align-middle inline-block"
>
{/* Logo Section */}
<div className="flex flex-col space-y-10">
<div className="flex-grow mx-auto">
karlromets marked this conversation as resolved.
Show resolved Hide resolved
{props.game.settings.logo_url ? (
Expand All @@ -43,11 +46,28 @@ export default function Title(props) {
<TitleLogo insert={props.game.title_text} size={titleSize} />
)}
</div>

{/* Room Code Section */}
<div className="flex flex-row justify-center text-center">
<p className="text-4xl font-bold p-5 text-foreground rounded bg-secondary-500">
{props.game.room}
</p>
<div className="flex flex-col items-center">
<div className="text-xl font-semibold text-foreground p-0.5 px-2 pb-0 rounded-t-xl bg-secondary-500 shadow-lg">{t("Room Code")}</div>
<p className="text-6xl font-bold p-6 text-foreground rounded-xl bg-secondary-500 shadow-lg">
{props.game.room}
</p>
</div>
</div>

{/* URL Section */}
{process.env.NEXT_PUBLIC_TITLE_URL && (
<div className="flex flex-row justify-center text-center mt-4">
<span
className="text-4xl p-6 text-foreground rounded-xl bg-secondary-500 shadow-lg transition-colors duration-200"
>
{t("Join at")} <span className="font-bold">{process.env.NEXT_PUBLIC_TITLE_URL}</span>
</span>
</div>
)}
{/* Teams and players section */}
<div className="flex flex-row text-center">
{[0, 1].map(function(n) {
return (
Expand Down
4 changes: 3 additions & 1 deletion public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,7 @@
"donate": "donate",
"email": "email",
"source code": "source code",
"Question": "Question"
"Question": "Question",
"Join at": "Join at",
"Room Code": "Room Code"
}
4 changes: 3 additions & 1 deletion public/locales/et/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,7 @@
"donate": "annetama",
"email": "e -kiri",
"source code": "l\u00e4htekood",
"Question": "K\u00fcsitlus"
"Question": "K\u00fcsitlus",
"Join at": "Liitu: ",
"Room Code": "Ruumi Kood"
}
37 changes: 37 additions & 0 deletions utils/files.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
export function handleJsonFile(file, { setError, t, send }) {
var reader = new FileReader();
reader.readAsText(file, "utf-8");
reader.onload = function(evt) {
try {
let data = JSON.parse(evt.target.result);
console.debug(data);
// TODO some error checking for invalid game data
send({ action: "load_game", data: data });
} catch (e) {
console.error("Invalid JSON file");
setError(t("Invalid JSON file"));
}
};
reader.onerror = function(evt) {
console.error("error reading file");
setError(t("error reading file"));
};
}

export function handleCsvFile(file, { setError, t, setCsvFileUpload, setCsvFileUploadText }) {
var reader = new FileReader();
reader.readAsText(file, "utf-8");
reader.onload = function(evt) {
let lineCount = evt.target.result.split("\n");
if (lineCount.length > 30) {
setError(t("This csv file is too large"));
} else {
setCsvFileUpload(file);
setCsvFileUploadText(evt.target.result);
}
};
reader.onerror = function(evt) {
console.error("error reading file");
setError(t("error reading file"));
};
}