Files
DOSSIER-STANDALONE/src/ui/LockConflictDialog.tsx
T
karim 35299307d6 Akkumulierten grünen Arbeitsstand landen (Basis für Weiterarbeit)
Bündelt den über mehrere Sessions gewachsenen, uncommitteten Stand in
einem Basis-Commit, damit Folge-Features isoliert darauf aufsetzen.
Verifikation: tsc --noEmit sauber, vitest 600/600 grün.

Enthalten (Details in PENDENZEN.md ✅-Liste / HANDOVER.md):
- truck-Integration: Profil-Extrusion + Verjüngung + Boolean-CSG (csgrs),
  Crate src-tauri/trucksolid, Werkzeug `extrude`, ExtrudedSolid-Modell.
- kernel2d-Port nach Rust/WASM (Phasen 1–5, Diff-Harness).
- render3d 3D-Live-Schnitt = 2D-Schnitt: geschichteter Bodenaufbau,
  Prioritäts-Verschneidung (section_boolean.rs), einstellbare
  Schichttrennlinien, per-Hatch-Strichstärke, relativeToWall-Orientierung.
- Interop-Export IFC4/STL/OBJ (Loch-Ausschnitt wallMeshCut), Schnellexport.
- Projektdatei .obp + OS-Lock (lock.rs, LockConflictDialog).
- Layout-Blätter (Modell/Editor/Panel/PDF), Ausschnitte, Override-Engine,
  Tragwerk-Stützen (Column), BIM-Tree-Panel.
- Bauteil-Typsystem (Tür/Fenster/Treppe-Typen), Betontreppe mit schräger
  Laufplatte, Text-/Textbox-Werkzeug, Mess-Werkzeug, 2D/3D-Griffe für
  Öffnungen/Treppen, Snap-Symbol-Restyle.
2026-07-09 00:57:29 +02:00

76 lines
2.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Meldung, wenn eine Projektdatei bereits in einer anderen Instanz gesperrt ist
// (Lock-Konflikt, s. src/io/projectFile.ts acquireProjectLock). Ersetzt
// `window.confirm` (im Tauri-WKWebView deaktiviert) — gleiches Overlay-Muster
// wie PromptDialog (imp-overlay/imp-dialog/imp-head/imp-body/imp-foot/imp-btn).
import { useEffect } from "react";
import { t } from "../i18n";
import type { LockInfo } from "../io/projectFile";
export interface LockConflictDialogProps {
/** Info aus der Lock-Sidecar-Datei (pid/hostname/timestamp) — kann fehlen. */
info: LockInfo | null;
/** Projekt ohne Lock nur lesend öffnen (kein Schreibzugriff-Anspruch). */
onReadOnly: () => void;
/** Lock ignorieren und trotzdem schreibend öffnen (Risiko: zwei Schreiber). */
onForceOpen: () => void;
onCancel: () => void;
}
export function LockConflictDialog({
info,
onReadOnly,
onForceOpen,
onCancel,
}: LockConflictDialogProps) {
useEffect(() => {
const onKey = (e: KeyboardEvent) => {
if (e.key === "Escape") onCancel();
};
window.addEventListener("keydown", onKey);
return () => window.removeEventListener("keydown", onKey);
}, [onCancel]);
return (
<div className="imp-overlay" onClick={onCancel}>
<div
className="imp-dialog"
role="dialog"
aria-modal="true"
aria-label={t("lock.title")}
onClick={(e) => e.stopPropagation()}
>
<header className="imp-head">
<span className="imp-head-title">{t("lock.title")}</span>
<button className="imp-close" onClick={onCancel} aria-label={t("export.close")}>
×
</button>
</header>
<div className="imp-body">
<section className="imp-section">
<div className="imp-section-title">{t("lock.message")}</div>
{info && (
<div className="imp-section-title" style={{ opacity: 0.7, fontWeight: 400 }}>
{t("lock.messageInfo", { host: info.hostname, pid: String(info.pid) })}
</div>
)}
</section>
</div>
<footer className="imp-foot">
<button className="imp-btn" onClick={onCancel}>
{t("export.cancel")}
</button>
<button className="imp-btn danger" onClick={onForceOpen} title={t("lock.forceOpenWarning")}>
{t("lock.forceOpen")}
</button>
<button className="imp-btn primary" onClick={onReadOnly}>
{t("lock.openReadOnly")}
</button>
</footer>
</div>
</div>
);
}