refactoring-backend #3

Merged
lukas.pupkalipinski merged 403 commits from refactoring-backend into main 2026-05-20 20:23:46 +02:00
15 changed files with 1395655 additions and 31 deletions
Showing only changes of commit a286ede49c - Show all commits

View File

@@ -611,7 +611,11 @@ Do **not** add a Content-Security-Policy meta tag; CSP should be set as an HTTP
---
### TASK-030 — Add manual chunk splitting to `vite.config.ts`
### TASK-030 — Add manual chunk splitting to `vite.config.ts` (done)
**Where fixed:** `frontend/vite.config.ts`
**Summary:** Implemented `build.rollupOptions.output.manualChunks` function that groups modules into four vendor chunks: `react-vendor`, `ui-vendor`, `chart-vendor`, and `geo-vendor`. This ensures stable, cacheable chunks across deployments.
**Where found:** `frontend/vite.config.ts``build` section is absent entirely; Rollup uses its default single-chunk strategy.

View File

@@ -1,10 +1,11 @@
import js from "@eslint/js";
import tseslint from "typescript-eslint";
import reactHooks from "eslint-plugin-react-hooks";
import reactPlugin from "eslint-plugin-react";
import prettierConfig from "eslint-config-prettier";
export default tseslint.config(
{ ignores: ["dist", "eslint.config.ts"] },
{ ignores: ["dist", "eslint.config.ts", ".vite"] },
{
extends: [js.configs.recommended, ...tseslint.configs.strictTypeChecked],
files: ["**/*.{ts,tsx}"],
@@ -15,10 +16,21 @@ export default tseslint.config(
},
},
plugins: {
react: reactPlugin,
"react-hooks": reactHooks,
},
settings: {
react: {
version: "detect",
},
},
rules: {
...reactHooks.configs.recommended.rules,
"@typescript-eslint/no-floating-promises": "error",
"@typescript-eslint/no-misused-promises": "error",
"react/no-array-index-key": "warn",
"react/no-unstable-nested-components": "error",
"@typescript-eslint/switch-exhaustiveness-check": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/explicit-function-return-type": "warn",
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }],

File diff suppressed because it is too large Load Diff

View File

@@ -21,26 +21,27 @@
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^6.27.0",
"recharts": "^3.8.0",
"topojson-client": "^3.1.0",
"world-atlas": "^2.0.2",
"recharts": "^3.8.0"
"world-atlas": "^2.0.2"
},
"devDependencies": {
"@types/d3-geo": "^3.1.0",
"@types/topojson-client": "^3.0.0",
"@eslint/js": "^9.13.0",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^16.3.2",
"@testing-library/user-event": "^14.6.1",
"@types/d3-geo": "^3.1.0",
"@types/node": "^25.3.2",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@types/topojson-client": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^8.13.0",
"@typescript-eslint/parser": "^8.13.0",
"@vitejs/plugin-react": "^4.3.3",
"@vitest/coverage-v8": "^4.0.18",
"eslint": "^9.13.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^5.0.0",
"jiti": "^2.6.1",
"jsdom": "^28.1.0",

View File

@@ -188,9 +188,9 @@ export const TopCountriesPieChart = memo(function TopCountriesPieChart({
}}
labelLine={false}
>
{slices.map((slice, index) => (
{slices.map((slice) => (
// eslint-disable-next-line @typescript-eslint/no-deprecated
<Cell key={index} fill={slice.fill} />
<Cell key={slice.name} fill={slice.fill} />
))}
</Pie>
<Tooltip content={PieTooltip} />

View File

@@ -227,7 +227,7 @@ export function ActivateJailDialog({
<strong>Configuration errors detected:</strong>
<ul style={{ margin: `${tokens.spacingVerticalXS} 0 0 0`, paddingLeft: "1.2em" }}>
{blockingIssues.map((issue, idx) => (
<li key={idx}><em>{issue.field}:</em> {issue.message}</li>
<li key={issue.field + "-" + String(idx)}><em>{issue.field}:</em> {issue.message}</li>
))}
</ul>
</MessageBarBody>
@@ -242,7 +242,7 @@ export function ActivateJailDialog({
<strong>Advisory warnings:</strong>
<ul style={{ margin: `${tokens.spacingVerticalXS} 0 0 0`, paddingLeft: "1.2em" }}>
{advisoryIssues.map((issue, idx) => (
<li key={idx}><em>{issue.field}:</em> {issue.message}</li>
<li key={issue.field + "-" + String(idx)}><em>{issue.field}:</em> {issue.message}</li>
))}
</ul>
</MessageBarBody>
@@ -257,16 +257,12 @@ export function ActivateJailDialog({
<strong>Post-activation warnings:</strong>
<ul style={{ margin: `${tokens.spacingVerticalXS} 0 0 0`, paddingLeft: "1.2em" }}>
{validationWarnings.map((w, idx) => (
<li key={idx}>{w}</li>
<li key={w + "-" + String(idx)}>{w}</li>
))}
</ul>
</MessageBarBody>
</MessageBar>
)}
<Text block weight="semibold" style={{ marginBottom: tokens.spacingVerticalS }}>
Override values (leave blank to use config defaults)
</Text>
<div
style={{
display: "grid",

View File

@@ -114,7 +114,7 @@ export function CreateActionDialog({
.finally(() => {
setSubmitting(false);
});
}, [name, actionban, actionunban, submitting, onCreate]);
}, [name, actionban, actionunban, submitting, onCreate, onCreateAction]);
const canConfirm = name.trim() !== "" && !submitting;

View File

@@ -123,7 +123,7 @@ export function CreateFilterDialog({
.finally(() => {
setSubmitting(false);
});
}, [name, failregex, ignoreregex, submitting, onCreate]);
}, [name, failregex, ignoreregex, submitting, onCreate, onCreateFilter]);
const canConfirm = name.trim() !== "" && !submitting;

View File

@@ -101,7 +101,7 @@ export function CreateJailDialog({
.finally(() => {
setSubmitting(false);
});
}, [name, submitting, onCreated]);
}, [name, submitting, onCreated, onCreateJail]);
const canConfirm = name.trim() !== "" && !submitting;

View File

@@ -714,7 +714,7 @@ function InactiveJailDetail({
<strong>Errors:</strong>
<ul style={{ margin: `4px 0 0 0`, paddingLeft: "1.2em" }}>
{blockingIssues.map((issue, idx) => (
<li key={idx}><em>{issue.field}:</em> {issue.message}</li>
<li key={`${issue.field}-${String(idx)}`}><em>{issue.field}:</em> {issue.message}</li>
))}
</ul>
</MessageBarBody>
@@ -726,7 +726,7 @@ function InactiveJailDetail({
<strong>Warnings:</strong>
<ul style={{ margin: `4px 0 0 0`, paddingLeft: "1.2em" }}>
{advisoryIssues.map((issue, idx) => (
<li key={idx}><em>{issue.field}:</em> {issue.message}</li>
<li key={`${issue.field}-${String(idx)}`}><em>{issue.field}:</em> {issue.message}</li>
))}
</ul>
</MessageBarBody>
@@ -814,7 +814,6 @@ export function JailsTab({ initialJail }: JailsTabProps): React.JSX.Element {
refreshInactiveJails();
}, [refresh, refreshInactiveJails]);
/** Unified list items: active jails first (from useJailConfigs), then inactive. */
const listItems = useMemo<Array<{ name: string; kind: "active" | "inactive" }>>(() => {
const activeItems = jails.map((j) => ({ name: j.name, kind: "active" as const }));
const activeNames = new Set(jails.map((j) => j.name));
@@ -913,7 +912,7 @@ export function JailsTab({ initialJail }: JailsTabProps): React.JSX.Element {
key={selectedActiveJail.name}
jail={selectedActiveJail}
onSave={updateJail}
onDeactivate={() => { handleDeactivate(selectedActiveJail.name); }}
onDeactivate={() => { void handleDeactivate(selectedActiveJail.name); }}
/>
) : selectedInactiveJail !== undefined ? (
<InactiveJailDetail
@@ -922,10 +921,10 @@ export function JailsTab({ initialJail }: JailsTabProps): React.JSX.Element {
onActivate={() => { setActivateTarget(selectedInactiveJail); }}
onDeactivate={
selectedInactiveJail.has_local_override
? (): void => { handleDeactivateInactive(selectedInactiveJail.name); }
? (): void => { void handleDeactivateInactive(selectedInactiveJail.name); }
: undefined
}
onValidate={() => validateJailConfig(selectedInactiveJail.name)}
onValidate={() => { void validateJailConfig(selectedInactiveJail.name); }}
/>
) : null}
</ConfigListDetail>

View File

@@ -134,7 +134,7 @@ export function RegexTesterTab(): React.JSX.Element {
</Text>
{result.groups.map((g, i) => (
<Badge
key={i}
key={`${g}-${String(i)}`}
appearance="tint"
color="informative"
style={{ marginLeft: tokens.spacingHorizontalXS }}
@@ -206,7 +206,7 @@ export function RegexTesterTab(): React.JSX.Element {
<div className={styles.previewArea}>
{preview.lines.map((ln, idx) => (
<div
key={idx}
key={ln.line + "-" + String(idx)}
className={`${styles.logLine} ${ln.matched ? styles.matched : styles.notMatched}`}
>
{ln.line}

View File

@@ -15,7 +15,7 @@ export function CodeList({ items, empty }: CodeListProps): React.JSX.Element {
return (
<div className={styles.codeList}>
{items.map((item, i) => (
<span key={i} className={styles.codeItem}>
<span key={`${item}-${String(i)}`} className={styles.codeItem}>
{item}
</span>
))}

522575
node:fs Normal file

File diff suppressed because it is too large Load Diff

435524
path Normal file

File diff suppressed because it is too large Load Diff

435524
vite Normal file

File diff suppressed because it is too large Load Diff