Compare commits
No commits in common. "3d6458ffb028e934ab813d384088023f514972de" and "5d0a5ab3c3e939368fa3446aa16611f7d8ab9472" have entirely different histories.
3d6458ffb0
...
5d0a5ab3c3
|
|
@ -7,7 +7,6 @@ import type { Kennzahl } from "../types/kpi";
|
||||||
import { typeDisplayMapping } from "../types/kpi";
|
import { typeDisplayMapping } from "../types/kpi";
|
||||||
import Snackbar from "@mui/material/Snackbar";
|
import Snackbar from "@mui/material/Snackbar";
|
||||||
import MuiAlert from "@mui/material/Alert";
|
import MuiAlert from "@mui/material/Alert";
|
||||||
import { API_HOST } from "../util/api";
|
|
||||||
|
|
||||||
|
|
||||||
interface KPIFormProps {
|
interface KPIFormProps {
|
||||||
|
|
@ -30,7 +29,6 @@ const emptyKPI: Partial<Kennzahl> = {
|
||||||
|
|
||||||
export function KPIForm({ mode, initialData, onSave, onCancel, loading = false, resetTrigger }: KPIFormProps) {
|
export function KPIForm({ mode, initialData, onSave, onCancel, loading = false, resetTrigger }: KPIFormProps) {
|
||||||
const [formData, setFormData] = useState<Partial<Kennzahl>>(emptyKPI);
|
const [formData, setFormData] = useState<Partial<Kennzahl>>(emptyKPI);
|
||||||
const [originalExamples, setOriginalExamples] = useState<Array<{ sentence: string; value: string }>>([]);
|
|
||||||
const [isSaving, setIsSaving] = useState(false);
|
const [isSaving, setIsSaving] = useState(false);
|
||||||
const [snackbarOpen, setSnackbarOpen] = useState(false);
|
const [snackbarOpen, setSnackbarOpen] = useState(false);
|
||||||
const [snackbarMessage, setSnackbarMessage] = useState("");
|
const [snackbarMessage, setSnackbarMessage] = useState("");
|
||||||
|
|
@ -39,20 +37,14 @@ export function KPIForm({ mode, initialData, onSave, onCancel, loading = false,
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mode === 'edit' && initialData) {
|
if (mode === 'edit' && initialData) {
|
||||||
setOriginalExamples(initialData.examples || []);
|
setFormData(initialData);
|
||||||
setFormData({
|
|
||||||
...initialData,
|
|
||||||
examples: [{ sentence: '', value: '' }]
|
|
||||||
});
|
|
||||||
} else if (mode === 'add') {
|
} else if (mode === 'add') {
|
||||||
setOriginalExamples([]);
|
|
||||||
setFormData(emptyKPI);
|
setFormData(emptyKPI);
|
||||||
}
|
}
|
||||||
}, [mode, initialData]);
|
}, [mode, initialData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mode === 'add') {
|
if (mode === 'add') {
|
||||||
setOriginalExamples([]);
|
|
||||||
setFormData(emptyKPI);
|
setFormData(emptyKPI);
|
||||||
}
|
}
|
||||||
}, [resetTrigger]);
|
}, [resetTrigger]);
|
||||||
|
|
@ -72,30 +64,24 @@ export function KPIForm({ mode, initialData, onSave, onCancel, loading = false,
|
||||||
setSnackbarMessage("Mindestens ein Beispielsatz ist erforderlich");
|
setSnackbarMessage("Mindestens ein Beispielsatz ist erforderlich");
|
||||||
setSnackbarSeverity("error");
|
setSnackbarSeverity("error");
|
||||||
setSnackbarOpen(true);
|
setSnackbarOpen(true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newExamples = formData.examples.filter(ex => ex.sentence?.trim() && ex.value?.trim());
|
for (const ex of formData.examples) {
|
||||||
|
|
||||||
if (newExamples.length === 0) {
|
|
||||||
setSnackbarMessage('Mindestens ein vollständiger Beispielsatz ist erforderlich.');
|
|
||||||
setSnackbarSeverity("error");
|
|
||||||
setSnackbarOpen(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const ex of newExamples) {
|
|
||||||
if (!ex.sentence?.trim() || !ex.value?.trim()) {
|
if (!ex.sentence?.trim() || !ex.value?.trim()) {
|
||||||
setSnackbarMessage('Alle Beispielsätze müssen vollständig sein.');
|
setSnackbarMessage('Alle Beispielsätze müssen vollständig sein.');
|
||||||
setSnackbarSeverity("error");
|
setSnackbarSeverity("error");
|
||||||
setSnackbarOpen(true);
|
setSnackbarOpen(true);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
setIsSaving(true);
|
setIsSaving(true);
|
||||||
try {
|
try {
|
||||||
const spacyEntries = generateSpacyEntries({ ...formData, examples: newExamples });
|
const spacyEntries = generateSpacyEntries(formData);
|
||||||
|
|
||||||
// Für jeden einzelnen Beispielsatz:
|
// Für jeden einzelnen Beispielsatz:
|
||||||
for (const entry of spacyEntries) {
|
for (const entry of spacyEntries) {
|
||||||
|
|
@ -106,7 +92,7 @@ export function KPIForm({ mode, initialData, onSave, onCancel, loading = false,
|
||||||
localStorage.setItem("spacyData", JSON.stringify(updated));
|
localStorage.setItem("spacyData", JSON.stringify(updated));
|
||||||
|
|
||||||
// POST Request an das Flask-Backend
|
// POST Request an das Flask-Backend
|
||||||
const response = await fetch(`${API_HOST}/api/spacy/append-training-entry/`, {
|
const response = await fetch("http://localhost:5050/api/spacy/append-training-entry", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json"
|
"Content-Type": "application/json"
|
||||||
|
|
@ -123,10 +109,6 @@ export function KPIForm({ mode, initialData, onSave, onCancel, loading = false,
|
||||||
console.log("SpaCy-Eintrag gespeichert:", data);
|
console.log("SpaCy-Eintrag gespeichert:", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
const allExamples = mode === 'edit'
|
|
||||||
? [...originalExamples, ...newExamples]
|
|
||||||
: newExamples;
|
|
||||||
|
|
||||||
// Dann in die DB speichern
|
// Dann in die DB speichern
|
||||||
await onSave({
|
await onSave({
|
||||||
name: formData.name!,
|
name: formData.name!,
|
||||||
|
|
@ -134,18 +116,11 @@ export function KPIForm({ mode, initialData, onSave, onCancel, loading = false,
|
||||||
type: formData.type || 'string',
|
type: formData.type || 'string',
|
||||||
position: formData.position ?? 0,
|
position: formData.position ?? 0,
|
||||||
active: formData.active ?? true,
|
active: formData.active ?? true,
|
||||||
examples: allExamples,
|
examples: formData.examples ?? [],
|
||||||
is_trained: false,
|
is_trained: false,
|
||||||
});
|
});
|
||||||
// Formular zurücksetzen:
|
// Formular zurücksetzen:
|
||||||
if (mode === 'add') {
|
setFormData(emptyKPI);
|
||||||
setFormData(emptyKPI);
|
|
||||||
} else {
|
|
||||||
setFormData(prev => ({
|
|
||||||
...prev,
|
|
||||||
examples: [{ sentence: '', value: '' }]
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
setSnackbarMessage("Beispielsätze gespeichert. Jetzt auf -Neu trainieren- klicken oder weitere Kennzahlen hinzufügen.");
|
setSnackbarMessage("Beispielsätze gespeichert. Jetzt auf -Neu trainieren- klicken oder weitere Kennzahlen hinzufügen.");
|
||||||
|
|
@ -265,69 +240,45 @@ export function KPIForm({ mode, initialData, onSave, onCancel, loading = false,
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Divider sx={{ my: 3 }} />
|
|
||||||
|
|
||||||
<Box mb={4}>
|
{mode === 'add' && (
|
||||||
<FormControlLabel
|
<>
|
||||||
control={
|
<Divider sx={{ my: 3 }} />
|
||||||
<Checkbox
|
<Box mb={4}>
|
||||||
checked={formData.active !== false}
|
<FormControlLabel
|
||||||
onChange={(e) => updateField('active', e.target.checked)}
|
control={
|
||||||
sx={{
|
<Checkbox
|
||||||
color: '#666666',
|
checked={formData.active !== false}
|
||||||
'&.Mui-checked': {
|
onChange={(e) => updateField('active', e.target.checked)}
|
||||||
color: '#333333',
|
sx={{ color: '#383838' }}
|
||||||
},
|
/>
|
||||||
'&:hover': {
|
}
|
||||||
backgroundColor: 'rgba(102, 102, 102, 0.04)',
|
label="Aktiv"
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
}
|
<Typography variant="body2" color="text.secondary" ml={4}>
|
||||||
label="Aktiv"
|
Die Kennzahl ist aktiv und wird angezeigt
|
||||||
/>
|
</Typography>
|
||||||
<Typography variant="body2" color="text.secondary" ml={4}>
|
</Box>
|
||||||
Die Kennzahl ist aktiv und wird angezeigt
|
<Box mt={3}>
|
||||||
</Typography>
|
<FormControlLabel
|
||||||
</Box>
|
control={
|
||||||
<Box mt={3}>
|
<Checkbox
|
||||||
<FormControlLabel
|
checked={formData.mandatory || false}
|
||||||
control={
|
onChange={(e) => updateField('mandatory', e.target.checked)}
|
||||||
<Checkbox
|
sx={{ color: '#383838' }}
|
||||||
checked={formData.mandatory || false}
|
/>
|
||||||
onChange={(e) => updateField('mandatory', e.target.checked)}
|
}
|
||||||
sx={{
|
label="Erforderlich"
|
||||||
color: '#666666',
|
|
||||||
'&.Mui-checked': {
|
|
||||||
color: '#333333',
|
|
||||||
},
|
|
||||||
'&:hover': {
|
|
||||||
backgroundColor: 'rgba(102, 102, 102, 0.04)',
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
}
|
<Typography variant="body2" color="text.secondary" ml={4}>
|
||||||
label="Erforderlich"
|
Die Kennzahl erlaubt keine leeren Werte
|
||||||
/>
|
</Typography>
|
||||||
<Typography variant="body2" color="text.secondary" ml={4}>
|
</Box>
|
||||||
Die Kennzahl erlaubt keine leeren Werte
|
</>
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Divider sx={{ my: 3 }} />
|
|
||||||
|
|
||||||
{/* Hinweistext wie viele Beispielsätzen vorhanden sind*/}
|
|
||||||
{mode === 'edit' && originalExamples.length > 0 && (
|
|
||||||
<Box mb={2} p={2} sx={{ backgroundColor: '#e3f2fd', border: '1px solid #90caf9', borderRadius: 2 }}>
|
|
||||||
<Typography variant="body1" sx={{ fontWeight: 'bold', mb: 1 }}>
|
|
||||||
Vorhandene Beispielsätze: {originalExamples.length}
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="body2">
|
|
||||||
Diese Kennzahl hat bereits {originalExamples.length} Beispielsätze. Neue Beispielsätze werden zu den vorhandenen hinzugefügt.
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<Divider sx={{ my: 3 }} />
|
||||||
|
|
||||||
{/* Hinweistext vor Beispielsätzen */}
|
{/* Hinweistext vor Beispielsätzen */}
|
||||||
<Box mb={2} p={2} sx={{ backgroundColor: '#fff8e1', border: '1px solid #ffe082', borderRadius: 2 }}>
|
<Box mb={2} p={2} sx={{ backgroundColor: '#fff8e1', border: '1px solid #ffe082', borderRadius: 2 }}>
|
||||||
<Typography variant="body1" sx={{ fontWeight: 'bold', mb: 1 }}>
|
<Typography variant="body1" sx={{ fontWeight: 'bold', mb: 1 }}>
|
||||||
|
|
|
||||||
|
|
@ -188,10 +188,6 @@ export default function PDFViewer({
|
||||||
);
|
);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const contentWidth = baseWidth ? baseWidth * 0.98 * zoomLevel : 0;
|
|
||||||
const containerWidth = baseWidth ? baseWidth : 0;
|
|
||||||
const willOverflow = contentWidth > containerWidth;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
display="flex"
|
display="flex"
|
||||||
|
|
@ -201,6 +197,11 @@ export default function PDFViewer({
|
||||||
width="100%"
|
width="100%"
|
||||||
maxWidth="850px"
|
maxWidth="850px"
|
||||||
margin="0 auto"
|
margin="0 auto"
|
||||||
|
sx={{
|
||||||
|
backgroundColor: "#f5f5f5",
|
||||||
|
borderRadius: 2,
|
||||||
|
boxShadow: 2,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
ref={containerRef}
|
ref={containerRef}
|
||||||
|
|
@ -212,10 +213,11 @@ export default function PDFViewer({
|
||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
boxShadow: "none",
|
boxShadow: "none",
|
||||||
overflow: "auto",
|
overflow: "auto",
|
||||||
display: willOverflow ? "block" : "flex",
|
display: "flex",
|
||||||
justifyContent: willOverflow ? "flex-start" : "center",
|
justifyContent: "center",
|
||||||
alignItems: willOverflow ? "flex-start" : "center",
|
alignItems: "center",
|
||||||
padding: willOverflow ? `${Math.max(0, (500 - (contentWidth * (500 / containerWidth))) / 2)}px ${Math.max(0, (containerWidth - contentWidth) / 2)}px` : 0,
|
marginTop: 2,
|
||||||
|
marginBottom: 2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Document
|
<Document
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue