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,
"singleQuote": true,
"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
// 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)
const backendRes = await fetch(backendUrl, {
@@ -33,21 +34,26 @@ export async function redirectRequest(
status: backendRes.status,
headers: {
'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.
/// 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)
return new NextResponse(null, {
status: 200,
headers: {
'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': '*',
// req.headers.get('access-control-request-headers') || 'Content-Type, Authorization'
},
@@ -1,12 +1,19 @@
import type { NextRequest } 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 { appConfig } from '@/lib/configLoader'
// Forwards the incoming request to the save parser backend.
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
+25 -7
View File
@@ -1,7 +1,11 @@
'use client'
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'
// 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.
useEffect(() => {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
setAgTheme(prefersDark ? themeQuartz.withPart(colorSchemeDark) : themeQuartz)
const prefersDark = window.matchMedia(
'(prefers-color-scheme: dark)'
).matches
setAgTheme(
prefersDark ? themeQuartz.withPart(colorSchemeDark) : themeQuartz
)
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 () => {
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' },
]}
columnDefs={[
{ field: 'col1', headerName: 'Column 1', filter: 'agTextColumnFilter' },
{
field: 'col1',
headerName: 'Column 1',
filter: 'agTextColumnFilter',
},
{ 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.
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
export default function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
// Register the ag-grid community features
ModuleRegistry.registerModules([AllCommunityModule])
return (
+5 -2
View File
@@ -14,7 +14,7 @@ export default function LoginPage() {
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 { name, value, type, checked } = e.target
setFormData((prev) => ({
@@ -30,7 +30,10 @@ export default function LoginPage() {
setError(null)
try {
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)
} catch (err: any) {
console.error(err.message)
+5 -1
View File
@@ -36,7 +36,11 @@ export default function RegisterPage() {
}
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)
router.push('/login') // Redirect after success
} 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.
export default function Navbar() {
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">
{/* Left: Home Link */}
<Link href="/" className="navbar-brand">
@@ -15,10 +17,16 @@ export default function Navbar() {
{/* Right: Login/Register Buttons */}
<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
</Link>
<Link href="/register" className="btn btn-primary rounded-pill px-4">
<Link
href="/register"
className="btn btn-primary rounded-pill px-4"
>
Register
</Link>
</div>
+25 -6
View File
@@ -1,6 +1,10 @@
'use client'
import { saveParserBackendService, SaveStatusResponse, UploadSaveResponse } from '@/services/SaveParserBackendService'
import {
saveParserBackendService,
SaveStatusResponse,
UploadSaveResponse,
} from '@/services/SaveParserBackendService'
import { useState } from 'react'
import FormError from './FormError'
@@ -18,8 +22,12 @@ export default function SaveFileUploadingDialog() {
const [selectedFile, setSelectedFile] = useState<File | null>(null)
const [game, setGame] = useState<GameEnum>(GameEnum.EU4)
const [uploadDisabled, setUploadDisabled] = useState(false)
const [saveStatus, setSaveStatus] = useState<SaveStatusResponse | null>(null)
const [uploadResult, setUploadResult] = useState<UploadSaveResponse | null>(null)
const [saveStatus, setSaveStatus] = useState<SaveStatusResponse | null>(
null
)
const [uploadResult, setUploadResult] = useState<UploadSaveResponse | null>(
null
)
// Update the selected game from the dropdown.
const handleGameSelect = (e: React.ChangeEvent<HTMLSelectElement>) => {
@@ -42,7 +50,10 @@ export default function SaveFileUploadingDialog() {
if (!selectedFile) return
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)
setUploadResult(uploadResponse)
@@ -50,7 +61,10 @@ export default function SaveFileUploadingDialog() {
// Poll the backend every second for the parsing status until it reports "done".
const intervalId = setInterval(async () => {
try {
const statusResponse = await saveParserBackendService.getSaveStatus(uploadResponse.id)
const statusResponse =
await saveParserBackendService.getSaveStatus(
uploadResponse.id
)
console.log('Save status:', statusResponse.status)
setSaveStatus(statusResponse)
if (statusResponse.status.toLowerCase() === 'done') {
@@ -100,7 +114,12 @@ export default function SaveFileUploadingDialog() {
<label htmlFor="fileInput" className="form-label">
Select File
</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
className="btn btn-primary w-100 mt-1 mb-3"
+12 -3
View File
@@ -36,7 +36,10 @@ export class SaveParserBackendService {
})
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()
@@ -48,7 +51,10 @@ export class SaveParserBackendService {
const response = await fetch(url)
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()
@@ -60,7 +66,10 @@ export class SaveParserBackendService {
const response = await fetch(url)
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()