fix: resolve EACCES permission issue and hydration error #418

This commit is contained in:
Michael committed 2026-02-21 12:54:39 +01:00
1 parent 0026e3134d
commit 4f4a0dbd62
4 files changed
+45 -13

No files matched your search

+6 -3
View File
@@ -37,15 +37,18 @@ RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
# Set the correct permission for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next
# Set the correct permission for prerender cache and data storage
RUN mkdir .next data
RUN chown nextjs:nodejs .next data
# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
# Grant write access to /app for settings persistence
RUN chown -R nextjs:nodejs /app
USER nextjs
EXPOSE 5643
+1 -1
View File
@@ -8,7 +8,7 @@ let connectionString = process.env.DATABASE_URL;
// On tente de lire la config sauvegardée via l'UI
try {
const CONFIG_PATH = path.join(process.cwd(), ".db-config.json");
const CONFIG_PATH = path.join(process.cwd(), "data", ".db-config.json");
if (fs.existsSync(CONFIG_PATH)) {
const config = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
if (config.url) {
+24 -2
View File
@@ -31,7 +31,7 @@ function getLast12Months(): string[] {
return months;
}
const MONTHS_12 = getLast12Months();
// La constante est supprimée d'ici pour éviter le mismatch d'hydratation (new Date() au runtime module)
function formatMonthLabel(key: string): string {
const m = parseInt(key.slice(4, 6), 10);
@@ -47,10 +47,17 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
const { rows, draftChanges, setDraftGamme, filters, displayDensity } = useGridStore();
const [sorting, setSorting] = useState<SortingState>([]);
const [rowSelection, setRowSelection] = useState<RowSelectionState>({});
const [isMounted, setIsMounted] = useState(false);
const tableContainerRef = useRef<HTMLDivElement>(null);
// Calculer les mois dynamiquement pour éviter le mismatch entre serveur et client
const MONTHS_12 = useMemo(() => getLast12Months(), []);
useEffect(() => {
setIsMounted(true);
}, []);
const rowHeight = displayDensity === "compact" ? 32 : displayDensity === "normal" ? 40 : 48;
const cellPadding = displayDensity === "compact" ? "py-1" : displayDensity === "normal" ? "py-1.5" : "py-2.5";
const handleRowSelectionChange = useCallback(
(updater: React.SetStateAction<RowSelectionState>) => {
@@ -241,6 +248,21 @@ export function HeatmapGrid({ onSelectionChange }: HeatmapGridProps) {
const totalWidth = columns.reduce((s, c) => s + ((c as { size?: number }).size ?? 150), 0);
if (!isMounted) {
return (
<div
className="overflow-auto rounded-[12px] flex items-center justify-center"
style={{
height: "calc(100vh - 240px)",
background: "var(--bg-surface)",
border: "1px solid var(--border)",
}}
>
<div className="text-muted text-sm italic opacity-50">Chargement de la grille...</div>
</div>
);
}
return (
<div
ref={tableContainerRef}
+14 -7
View File
@@ -4,7 +4,8 @@ import { Pool } from "pg";
import fs from "fs/promises";
import path from "path";
const CONFIG_FILE = path.join(process.cwd(), ".db-config.json");
const DATA_DIR = path.join(process.cwd(), "data");
const CONFIG_FILE = path.join(DATA_DIR, ".db-config.json");
export interface DbConfig {
url: string;
@@ -22,9 +23,10 @@ export async function testDatabaseConnection(url: string) {
await client.query("SELECT 1");
client.release();
return { success: true };
} catch (error: any) {
console.error("Database connection test failed:", error.message);
return { success: false, error: error.message };
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error("Database connection test failed:", errorMessage);
return { success: false, error: errorMessage };
} finally {
await pool.end();
}
@@ -33,12 +35,17 @@ export async function testDatabaseConnection(url: string) {
export async function saveDatabaseSettings(url: string) {
try {
const config: DbConfig = { url };
// S'assurer que le dossier data existe
await fs.mkdir(DATA_DIR, { recursive: true });
await fs.writeFile(CONFIG_FILE, JSON.stringify(config, null, 2));
console.log("Database configuration saved to:", CONFIG_FILE);
return { success: true };
} catch (error: any) {
console.error("Failed to save database configuration:", error.message);
return { success: false, error: error.message };
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : String(error);
console.error("Failed to save database configuration:", errorMessage);
return { success: false, error: errorMessage };
}
}