diff --git a/.gitignore b/.gitignore index 5ef6a52..7a2fd26 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ yarn-error.log* # env files (can opt-in for committing if needed) .env* +/runtimeConfig.json # vercel .vercel diff --git a/src/app/api/proxy/proxyFunctions.ts b/src/app/api/proxy/functions.ts similarity index 88% rename from src/app/api/proxy/proxyFunctions.ts rename to src/app/api/proxy/functions.ts index 27fa824..7c2b6a3 100644 --- a/src/app/api/proxy/proxyFunctions.ts +++ b/src/app/api/proxy/functions.ts @@ -8,7 +8,7 @@ export async function redirectRequest( proxyUrl: string, backendBaseUrl: string ): Promise { - const reqUrl = req.url // full URL e.g. http://localhost:3000/api/proxy?id=123&foo=bar + const reqUrl = req.url // full URL e.g. http://localhost:3000/api/proxy?id=123 // Find position of proxyPath in reqUrl const proxyIndex = reqUrl.indexOf(proxyUrl) @@ -17,9 +17,9 @@ export async function redirectRequest( } // Replace '/api/proxy/parserBackend' with backend URL, preserve everything after - // e.g. '/api/proxy/extra/path?id=123' -> 'http://your-backend-server/extra/path?id=123' + // e.g. '/api/proxy/extra/path?id=123' -> 'http://backend-server/extra/path?id=123' const backendUrl = backendBaseUrl + reqUrl.substring(proxyIndex + proxyUrl.length) - console.log('redirecting', req.url, 'to', backendUrl) + // console.log('redirecting', req.url, 'to', backendUrl) const backendRes = await fetch(backendUrl, { method: req.method, @@ -41,7 +41,7 @@ export async function redirectRequest( /// Browsers send OPTIONS request sometimes to check webserver allowed headers and methods. /// My backend doesn't support such requests so use proxy to answer to it that all headers and methods are allowed export async function responseToOPTIONS(req: NextRequest): Promise { - console.log('proxy responding to CORS OPTIONS', req.url) + // console.log('proxy responding to CORS OPTIONS', req.url) return new NextResponse(null, { status: 200, diff --git a/src/app/api/proxy/saveParserBackend/[[...path]]/route.ts b/src/app/api/proxy/saveParserBackend/[[...path]]/route.ts index 508a147..4ff91e3 100644 --- a/src/app/api/proxy/saveParserBackend/[[...path]]/route.ts +++ b/src/app/api/proxy/saveParserBackend/[[...path]]/route.ts @@ -1,8 +1,8 @@ import type { NextRequest } from 'next/server' import { NextResponse } from 'next/server' -import { redirectRequest, responseToOPTIONS as respondToOPTIONS } from '@/app/api/proxy/proxyFunctions' -import { appConfig } from '@/app/lib/configLoader' -import { PROXY_PATHS } from '../../paths' +import { redirectRequest, responseToOPTIONS as respondToOPTIONS } from '@/app/api/proxy/functions' +import { PROXY_PATHS } from '@/app/api/proxy/paths' +import { appConfig } from '@/lib/configLoader' async function redirect(req: NextRequest): Promise { return await redirectRequest(req, PROXY_PATHS.saveParserBackend, appConfig.services.saveParserBackend.url) diff --git a/src/app/layout.tsx b/src/app/layout.tsx index eb97a07..0f94fe8 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,6 +1,5 @@ import 'bootstrap/dist/css/bootstrap.min.css' import './globals.css' -import '@/app/lib/customConsoleLog' import type { Metadata } from 'next' import { ModuleRegistry, AllCommunityModule } from 'ag-grid-community' import Navbar from '@/components/Navbar' diff --git a/src/app/login/page.tsx b/src/app/login/page.tsx index 9a1118f..5330d63 100644 --- a/src/app/login/page.tsx +++ b/src/app/login/page.tsx @@ -23,6 +23,7 @@ export default function LoginPage() { const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() + setError(null) try { console.log('Log in:', formData) const result = await authService.login(formData.email, formData.password) diff --git a/src/app/register/page.tsx b/src/app/register/page.tsx index e03cf45..f81c109 100644 --- a/src/app/register/page.tsx +++ b/src/app/register/page.tsx @@ -26,6 +26,7 @@ export default function RegisterPage() { const handleSubmit = async (e: React.FormEvent) => { e.preventDefault() + setError(null) try { if (formData.password !== formData.confirmPassword) { throw new Error('Passwords do not match.') @@ -34,7 +35,6 @@ export default function RegisterPage() { console.log('Register', formData) const result = await authService.register(formData.name, formData.email, formData.password) console.log('Registered:', result) - router.push('/login') // Redirect after success } catch (err: any) { console.error(err.message) diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index a5b4e0f..c6acb70 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -1,7 +1,7 @@ 'use client' import Link from 'next/link' -import { font_Hack } from '@/app/lib/myFonts' +import { font_Hack } from '@/lib/myFonts' export default function Navbar() { return ( diff --git a/src/components/SaveFileUploadingDialog.tsx b/src/components/SaveFileUploadingDialog.tsx index 2e089c1..878be49 100644 --- a/src/components/SaveFileUploadingDialog.tsx +++ b/src/components/SaveFileUploadingDialog.tsx @@ -1,6 +1,6 @@ 'use client' -import { saveParserBackendService, UploadSaveResponse } from '@/services/SaveParserBackendService' +import { saveParserBackendService, SaveStatusResponse, UploadSaveResponse } from '@/services/SaveParserBackendService' import { useState } from 'react' import FormError from './FormError' @@ -13,8 +13,14 @@ export default function SaveFileUploadingDialog() { const [error, setError] = useState(null) const [selectedFile, setSelectedFile] = useState(null) const [game, setGame] = useState(GameEnum.EU4) + const [uploadDisabled, setUploadDisabled] = useState(false) + const [saveStatus, setSaveStatus] = useState(null) const [uploadResult, setUploadResult] = useState(null) + const handleGameSelect = (e: React.ChangeEvent) => { + setGame(e.target.value as GameEnum) + } + const handleFileChange = (e: React.ChangeEvent) => { if (e.target.files && e.target.files[0]) { setSelectedFile(e.target.files[0]) @@ -22,58 +28,78 @@ export default function SaveFileUploadingDialog() { } const handleUpload = async () => { + setError(null) + setUploadDisabled(true) try { if (!selectedFile) return console.log('Uploading file:', selectedFile.name) - const result = await saveParserBackendService.uploadSave(game, selectedFile) - console.log('Got response:', result) - setUploadResult(result) + const uploadResponse = await saveParserBackendService.uploadSave(game, selectedFile) + console.log('Upload response:', uploadResponse) + setUploadResult(uploadResponse) + + const pollInterval = 1000 // ms + const intervalId = setInterval(async () => { + try { + const statusResponse = await saveParserBackendService.getSaveStatus(uploadResponse.id) + console.log('Save status:', statusResponse.status) + setSaveStatus(statusResponse) + if (statusResponse.status.toLowerCase() === 'done') { + clearInterval(intervalId) + setUploadDisabled(false) + } + } catch (err: any) { + console.error('Error while polling status:', err) + clearInterval(intervalId) + setError(err.message) + setUploadDisabled(false) + } + }, pollInterval) } catch (err: any) { console.error(err.message) setError(err.message) + setUploadDisabled(false) } } + const gameEnumOptions = Object.values(GameEnum).map((value) => ( + + )) + return (

Select game save file

-
- - + {gameEnumOptions}
- - - {selectedFile && ( -
- File: {selectedFile.name} -
- )} - {uploadResult && (
Save Id: {uploadResult.id}
)} + + {saveStatus && ( +
+ Status: {saveStatus.status} +
+ )}
) } diff --git a/src/config/.gitignore b/src/config/.gitignore deleted file mode 100644 index caf3ec6..0000000 --- a/src/config/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/runtimeConfig.json diff --git a/src/config/defaultConfig.ts b/src/config/AppConfig.ts similarity index 100% rename from src/config/defaultConfig.ts rename to src/config/AppConfig.ts diff --git a/src/instrumentation.ts b/src/instrumentation.ts new file mode 100644 index 0000000..a501364 --- /dev/null +++ b/src/instrumentation.ts @@ -0,0 +1,5 @@ +import '@/lib/customConsoleLog' + +export function register() { + console.log('hello from instrumentation.ts!') +} diff --git a/src/lib/configLoader.ts b/src/lib/configLoader.ts index 9b7fb8c..eb43749 100644 --- a/src/lib/configLoader.ts +++ b/src/lib/configLoader.ts @@ -1,9 +1,9 @@ 'server' import fs from 'fs' import path from 'path' -import { AppConfig, defaultConfig } from '@/config/defaultConfig' +import { AppConfig, defaultConfig } from '@/config/AppConfig' -const configFilePath = path.join(process.cwd(), 'config', 'runtimeConfig.json') +const configFilePath = path.join(process.cwd(), 'runtimeConfig.json') function loadConfig(): AppConfig { let config = defaultConfig diff --git a/src/lib/customConsoleLog.ts b/src/lib/customConsoleLog.ts index a10549b..f696c99 100644 --- a/src/lib/customConsoleLog.ts +++ b/src/lib/customConsoleLog.ts @@ -1,8 +1,13 @@ -'server' -const originalLog = console.log +let _custom_console_log_injected = false +if (!_custom_console_log_injected) { + _custom_console_log_injected = true + const originalLog = console.log -console.log = (message?: any, ...optionalParams: any[]) => { - const now = new Date() - const timestamp = now.toTimeString().split(' ')[0] // hh:mm:ss - originalLog(`[${timestamp}] ${message}`, ...optionalParams) + function customLog(message?: any, ...optionalParams: any[]) { + const now = new Date() + const timestamp = now.toTimeString().split(' ')[0] // hh:mm:ss + originalLog(`[${timestamp}] ${message}`, ...optionalParams, ':3') + } + + console.log = customLog } diff --git a/src/services/SaveParserBackendService.ts b/src/services/SaveParserBackendService.ts index 4454e26..4a6bf87 100644 --- a/src/services/SaveParserBackendService.ts +++ b/src/services/SaveParserBackendService.ts @@ -1,3 +1,5 @@ +import { PROXY_PATHS } from '@/app/api/proxy/paths' + export interface UploadSaveResponse { id: string } @@ -10,7 +12,7 @@ export interface SaveStatusResponse { } export class SaveParserBackendService { - private API_BASE = '/api/proxy/parserBackend' + private API_BASE = PROXY_PATHS.saveParserBackend private async tryGetResponseJson(res: Response): Promise { try {