format: file width decreased from 120 to 80

This commit is contained in:
Altair-sh
2026-09-04 19:42:04 +02:00
parent 0ecac6533c
commit 8b556ac5cb
10 changed files with 107 additions and 31 deletions
+2 -2
View File
@@ -3,5 +3,5 @@
"semi": false, "semi": false,
"singleQuote": true, "singleQuote": true,
"trailingComma": "es5", "trailingComma": "es5",
"printWidth": 120 "printWidth": 80
} }
+10 -4
View File
@@ -18,7 +18,8 @@ export async function redirectRequest(
// Replace '/api/proxy/parserBackend' with backend URL, preserve everything after // Replace '/api/proxy/parserBackend' with backend URL, preserve everything after
// e.g. '/api/proxy/extra/path?id=123' -> 'http://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) 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, { const backendRes = await fetch(backendUrl, {
@@ -33,21 +34,26 @@ export async function redirectRequest(
status: backendRes.status, status: backendRes.status,
headers: { headers: {
'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Origin': '*',
'Content-Type': backendRes.headers.get('content-type') || 'application/octet-stream', 'Content-Type':
backendRes.headers.get('content-type') ||
'application/octet-stream',
}, },
}) })
} }
/// Browsers send OPTIONS request sometimes to check webserver's allowed headers and methods. /// Browsers send OPTIONS request sometimes to check webserver's allowed headers and methods.
/// My C# backend doesn't support OPTIONS, so the proxy answer to OPTIONS request that all headers and methods are allowed. /// My C# backend doesn't support OPTIONS, so the proxy answer to OPTIONS request that all headers and methods are allowed.
export async function responseToOPTIONS(req: NextRequest): Promise<NextResponse> { export async function responseToOPTIONS(
req: NextRequest
): Promise<NextResponse> {
// console.log('proxy responding to CORS OPTIONS', req.url) // console.log('proxy responding to CORS OPTIONS', req.url)
return new NextResponse(null, { return new NextResponse(null, {
status: 200, status: 200,
headers: { headers: {
'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, PATCH, DELETE, HEAD', 'Access-Control-Allow-Methods':
'GET, POST, PUT, PATCH, DELETE, HEAD',
'Access-Control-Allow-Headers': '*', 'Access-Control-Allow-Headers': '*',
// req.headers.get('access-control-request-headers') || 'Content-Type, Authorization' // req.headers.get('access-control-request-headers') || 'Content-Type, Authorization'
}, },
@@ -1,12 +1,19 @@
import type { NextRequest } from 'next/server' import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server' import { NextResponse } from 'next/server'
import { redirectRequest, responseToOPTIONS as respondToOPTIONS } from '@/app/api/proxy/functions' import {
redirectRequest,
responseToOPTIONS as respondToOPTIONS,
} from '@/app/api/proxy/functions'
import { PROXY_PATHS } from '@/app/api/proxy/paths' import { PROXY_PATHS } from '@/app/api/proxy/paths'
import { appConfig } from '@/lib/configLoader' import { appConfig } from '@/lib/configLoader'
// Forwards the incoming request to the save parser backend. // Forwards the incoming request to the save parser backend.
async function redirect(req: NextRequest): Promise<NextResponse> { async function redirect(req: NextRequest): Promise<NextResponse> {
return await redirectRequest(req, PROXY_PATHS.saveParserBackend, appConfig.services.saveParserBackend.url) return await redirectRequest(
req,
PROXY_PATHS.saveParserBackend,
appConfig.services.saveParserBackend.url
)
} }
// handlers for each request method on this route // handlers for each request method on this route
+25 -7
View File
@@ -1,7 +1,11 @@
'use client' 'use client'
import { AgGridReact } from 'ag-grid-react' import { AgGridReact } from 'ag-grid-react'
import { AllCommunityModule, themeQuartz, colorSchemeDark } from 'ag-grid-community' import {
AllCommunityModule,
themeQuartz,
colorSchemeDark,
} from 'ag-grid-community'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
// TODO: create tabs with general info, tables, plots // TODO: create tabs with general info, tables, plots
@@ -12,16 +16,26 @@ export default function BrowseSaveDataPage() {
// Keep the grid theme in sync with the browser's light/dark color scheme. // Keep the grid theme in sync with the browser's light/dark color scheme.
useEffect(() => { useEffect(() => {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches const prefersDark = window.matchMedia(
setAgTheme(prefersDark ? themeQuartz.withPart(colorSchemeDark) : themeQuartz) '(prefers-color-scheme: dark)'
).matches
setAgTheme(
prefersDark ? themeQuartz.withPart(colorSchemeDark) : themeQuartz
)
const listener = (e: MediaQueryListEvent) => { const listener = (e: MediaQueryListEvent) => {
setAgTheme(e.matches ? themeQuartz.withPart(colorSchemeDark) : themeQuartz) setAgTheme(
e.matches ? themeQuartz.withPart(colorSchemeDark) : themeQuartz
)
} }
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', listener) window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', listener)
return () => { return () => {
window.matchMedia('(prefers-color-scheme: dark)').removeEventListener('change', listener) window
.matchMedia('(prefers-color-scheme: dark)')
.removeEventListener('change', listener)
} }
}, []) }, [])
@@ -35,7 +49,11 @@ export default function BrowseSaveDataPage() {
{ id: 2, col1: 'Dark Mode', col2: 'Support' }, { id: 2, col1: 'Dark Mode', col2: 'Support' },
]} ]}
columnDefs={[ columnDefs={[
{ field: 'col1', headerName: 'Column 1', filter: 'agTextColumnFilter' }, {
field: 'col1',
headerName: 'Column 1',
filter: 'agTextColumnFilter',
},
{ field: 'col2', headerName: 'Column 2' }, { field: 'col2', headerName: 'Column 2' },
]} ]}
/> />
+3 -1
View File
@@ -9,7 +9,9 @@ export const metadata: Metadata = {
} }
// Root layout wrapping every page with the navbar and shared styles. // Root layout wrapping every page with the navbar and shared styles.
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) { export default function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
// Register the ag-grid community features // Register the ag-grid community features
ModuleRegistry.registerModules([AllCommunityModule]) ModuleRegistry.registerModules([AllCommunityModule])
return ( return (
+5 -2
View File
@@ -14,7 +14,7 @@ export default function LoginPage() {
const [error, setError] = useState<string | null>(null) const [error, setError] = useState<string | null>(null)
// Update the form data with new field value // Update the form data with new field value
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value, type, checked } = e.target const { name, value, type, checked } = e.target
setFormData((prev) => ({ setFormData((prev) => ({
@@ -30,7 +30,10 @@ export default function LoginPage() {
setError(null) setError(null)
try { try {
console.log('Log in:', formData) console.log('Log in:', formData)
const result = await authService.login(formData.email, formData.password) const result = await authService.login(
formData.email,
formData.password
)
console.log('Logged in:', result) console.log('Logged in:', result)
} catch (err: any) { } catch (err: any) {
console.error(err.message) console.error(err.message)
+5 -1
View File
@@ -36,7 +36,11 @@ export default function RegisterPage() {
} }
console.log('Register', formData) console.log('Register', formData)
const result = await authService.register(formData.name, formData.email, formData.password) const result = await authService.register(
formData.name,
formData.email,
formData.password
)
console.log('Registered:', result) console.log('Registered:', result)
router.push('/login') // Redirect after success router.push('/login') // Redirect after success
} catch (err: any) { } catch (err: any) {
+11 -3
View File
@@ -6,7 +6,9 @@ import { font_Hack } from '@/lib/myFonts'
// Top navigation bar with a home link and login/register buttons. // Top navigation bar with a home link and login/register buttons.
export default function Navbar() { export default function Navbar() {
return ( return (
<nav className={`navbar navbar-expand-lg navbar-dark bg-dark px-3 ${font_Hack.className}`}> <nav
className={`navbar navbar-expand-lg navbar-dark bg-dark px-3 ${font_Hack.className}`}
>
<div className="container-fluid"> <div className="container-fluid">
{/* Left: Home Link */} {/* Left: Home Link */}
<Link href="/" className="navbar-brand"> <Link href="/" className="navbar-brand">
@@ -15,10 +17,16 @@ export default function Navbar() {
{/* Right: Login/Register Buttons */} {/* Right: Login/Register Buttons */}
<div className="d-flex gap-2 ms-auto"> <div className="d-flex gap-2 ms-auto">
<Link href="/login" className="btn btn-outline-light rounded-pill px-4"> <Link
href="/login"
className="btn btn-outline-light rounded-pill px-4"
>
Log in Log in
</Link> </Link>
<Link href="/register" className="btn btn-primary rounded-pill px-4"> <Link
href="/register"
className="btn btn-primary rounded-pill px-4"
>
Register Register
</Link> </Link>
</div> </div>
+25 -6
View File
@@ -1,6 +1,10 @@
'use client' 'use client'
import { saveParserBackendService, SaveStatusResponse, UploadSaveResponse } from '@/services/SaveParserBackendService' import {
saveParserBackendService,
SaveStatusResponse,
UploadSaveResponse,
} from '@/services/SaveParserBackendService'
import { useState } from 'react' import { useState } from 'react'
import FormError from './FormError' import FormError from './FormError'
@@ -18,8 +22,12 @@ export default function SaveFileUploadingDialog() {
const [selectedFile, setSelectedFile] = useState<File | null>(null) const [selectedFile, setSelectedFile] = useState<File | null>(null)
const [game, setGame] = useState<GameEnum>(GameEnum.EU4) const [game, setGame] = useState<GameEnum>(GameEnum.EU4)
const [uploadDisabled, setUploadDisabled] = useState(false) const [uploadDisabled, setUploadDisabled] = useState(false)
const [saveStatus, setSaveStatus] = useState<SaveStatusResponse | null>(null) const [saveStatus, setSaveStatus] = useState<SaveStatusResponse | null>(
const [uploadResult, setUploadResult] = useState<UploadSaveResponse | null>(null) null
)
const [uploadResult, setUploadResult] = useState<UploadSaveResponse | null>(
null
)
// Update the selected game from the dropdown. // Update the selected game from the dropdown.
const handleGameSelect = (e: React.ChangeEvent<HTMLSelectElement>) => { const handleGameSelect = (e: React.ChangeEvent<HTMLSelectElement>) => {
@@ -42,7 +50,10 @@ export default function SaveFileUploadingDialog() {
if (!selectedFile) return if (!selectedFile) return
console.log('Uploading file:', selectedFile.name) console.log('Uploading file:', selectedFile.name)
const uploadResponse = await saveParserBackendService.uploadSave(game, selectedFile) const uploadResponse = await saveParserBackendService.uploadSave(
game,
selectedFile
)
console.log('Upload response:', uploadResponse) console.log('Upload response:', uploadResponse)
setUploadResult(uploadResponse) setUploadResult(uploadResponse)
@@ -50,7 +61,10 @@ export default function SaveFileUploadingDialog() {
// Poll the backend every second for the parsing status until it reports "done". // Poll the backend every second for the parsing status until it reports "done".
const intervalId = setInterval(async () => { const intervalId = setInterval(async () => {
try { try {
const statusResponse = await saveParserBackendService.getSaveStatus(uploadResponse.id) const statusResponse =
await saveParserBackendService.getSaveStatus(
uploadResponse.id
)
console.log('Save status:', statusResponse.status) console.log('Save status:', statusResponse.status)
setSaveStatus(statusResponse) setSaveStatus(statusResponse)
if (statusResponse.status.toLowerCase() === 'done') { if (statusResponse.status.toLowerCase() === 'done') {
@@ -100,7 +114,12 @@ export default function SaveFileUploadingDialog() {
<label htmlFor="fileInput" className="form-label"> <label htmlFor="fileInput" className="form-label">
Select File Select File
</label> </label>
<input id="fileInput" type="file" className="form-control mb-3" onChange={handleFileChange} /> <input
id="fileInput"
type="file"
className="form-control mb-3"
onChange={handleFileChange}
/>
<button <button
className="btn btn-primary w-100 mt-1 mb-3" className="btn btn-primary w-100 mt-1 mb-3"
+12 -3
View File
@@ -36,7 +36,10 @@ export class SaveParserBackendService {
}) })
if (!response.ok) { if (!response.ok) {
throw new Error(`Failed to upload save: ${response.statusText} ` + (await getBodyTextOrEmpty(response))) throw new Error(
`Failed to upload save: ${response.statusText} ` +
(await getBodyTextOrEmpty(response))
)
} }
return await response.json() return await response.json()
@@ -48,7 +51,10 @@ export class SaveParserBackendService {
const response = await fetch(url) const response = await fetch(url)
if (!response.ok) { if (!response.ok) {
throw new Error(`Failed to get save status: ${response.statusText} ` + (await getBodyTextOrEmpty(response))) throw new Error(
`Failed to get save status: ${response.statusText} ` +
(await getBodyTextOrEmpty(response))
)
} }
return await response.json() return await response.json()
@@ -60,7 +66,10 @@ export class SaveParserBackendService {
const response = await fetch(url) const response = await fetch(url)
if (!response.ok) { if (!response.ok) {
throw new Error(`Failed to get parsed save: ${response.statusText} ` + (await getBodyTextOrEmpty(response))) throw new Error(
`Failed to get parsed save: ${response.statusText} ` +
(await getBodyTextOrEmpty(response))
)
} }
return await response.json() return await response.json()