Compare commits
No commits in common. "a52c4c808e6f230e896832f0054c77b75f6fa9cc" and "0d09a825e9d1d5b4dd05a19a7d81da7897036fa2" have entirely different histories.
a52c4c808e
...
0d09a825e9
|
|
@ -3,14 +3,15 @@
|
|||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" href="/favicon.ico?v=1" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta
|
||||
name="description"
|
||||
content="Web site created using create-tsrouter-app"
|
||||
/>
|
||||
<link rel="apple-touch-icon" href="/logo192.png" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<title>Pitchbook Extractor</title>
|
||||
<title>Create TanStack App - frontend</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 3.8 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 5.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.4 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 50 KiB |
|
|
@ -184,10 +184,10 @@ export default function KennzahlenTable({
|
|||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell width="30%">
|
||||
<TableCell width="25%">
|
||||
<strong>Kennzahl</strong>
|
||||
</TableCell>
|
||||
<TableCell width="55%">
|
||||
<TableCell width="60%">
|
||||
<strong>Wert</strong>
|
||||
</TableCell>
|
||||
<TableCell align="center" width="15%">
|
||||
|
|
@ -226,11 +226,7 @@ export default function KennzahlenTable({
|
|||
|
||||
return (
|
||||
<TableRow key={row.setting.name}>
|
||||
<TableCell>{row.setting.name}
|
||||
{row.setting.mandatory && (
|
||||
<span> *</span>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>{row.setting.name}</TableCell>
|
||||
<TableCell
|
||||
onClick={() => {
|
||||
// Only allow inline editing for non-multiple value cells
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import SettingsIcon from "@mui/icons-material/Settings";
|
||||
import { Backdrop, Box, Button, IconButton, Paper, Typography } from "@mui/material";
|
||||
import { Backdrop, Box, Button, IconButton, Paper } from "@mui/material";
|
||||
import { useNavigate, useRouter } from "@tanstack/react-router";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
import FileUpload from "react-material-file-upload";
|
||||
import { socket } from "../socket";
|
||||
import { API_HOST } from "../util/api";
|
||||
import { CircularProgressWithLabel } from "./CircularProgressWithLabel";
|
||||
import DekaLogo from "../assets/Deka_logo.png";
|
||||
|
||||
export default function UploadPage() {
|
||||
const [files, setFiles] = useState<File[]>([]);
|
||||
|
|
@ -88,50 +87,26 @@ export default function UploadPage() {
|
|||
display="flex"
|
||||
flexDirection="column"
|
||||
alignItems="center"
|
||||
justifyContent="flex-start"
|
||||
justifyContent="center"
|
||||
height="100vh"
|
||||
bgcolor="white"
|
||||
pt={3}
|
||||
>
|
||||
<Box
|
||||
width="100%"
|
||||
maxWidth="1300px"
|
||||
display="flex"
|
||||
justifyContent="space-between"
|
||||
alignItems="center"
|
||||
px={8}
|
||||
py={5}
|
||||
justifyContent="flex-end"
|
||||
px={2}
|
||||
>
|
||||
<Box sx={{ display: "flex", alignItems: "center" }}>
|
||||
<img
|
||||
src={DekaLogo}
|
||||
alt="Company Logo"
|
||||
style={{ height: "40px", width: "auto" }}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<IconButton onClick={() => navigate({ to: "/config" })}>
|
||||
<SettingsIcon fontSize="large" />
|
||||
</IconButton>
|
||||
</Box>
|
||||
|
||||
<Typography
|
||||
variant="h4"
|
||||
component="h1"
|
||||
sx={{
|
||||
fontWeight: "bold",
|
||||
color: "#383838",
|
||||
marginBottom: 12,
|
||||
marginTop: 6,
|
||||
}}
|
||||
>
|
||||
Pitchbook Extractor
|
||||
</Typography>
|
||||
|
||||
<Paper
|
||||
elevation={3}
|
||||
sx={{
|
||||
width: 800,
|
||||
height: 400,
|
||||
width: 900,
|
||||
height: 500,
|
||||
backgroundColor: "#eeeeee",
|
||||
borderRadius: 4,
|
||||
display: "flex",
|
||||
|
|
@ -212,4 +187,4 @@ export default function UploadPage() {
|
|||
</Box>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,78 +95,53 @@ export default function PDFViewer({
|
|||
useEffect(() => {
|
||||
const tmpPos: string[] = [];
|
||||
const tmpPosHighlight: string[] = [];
|
||||
const textItems = textContent.filter(
|
||||
(e) => e.text !== "" && e.text !== " ",
|
||||
);
|
||||
|
||||
if (textContent.length === 0) {
|
||||
setPosHighlight([]);
|
||||
setPosHighlightFocus([]);
|
||||
return;
|
||||
}
|
||||
const findTextPositions = (searchText: string): number[] => {
|
||||
const positions: number[] = [];
|
||||
const normalizedSearch = searchText.toLowerCase().trim();
|
||||
|
||||
textContent.forEach((item, index) => {
|
||||
if (item.text.toLowerCase().trim() === normalizedSearch) {
|
||||
positions.push(index);
|
||||
}
|
||||
});
|
||||
|
||||
if (positions.length === 0) {
|
||||
let cumulativeText = '';
|
||||
const textBoundaries: { start: number; end: number; index: number }[] = [];
|
||||
|
||||
textContent.forEach((item, index) => {
|
||||
const start = cumulativeText.length;
|
||||
cumulativeText += item.text;
|
||||
const end = cumulativeText.length;
|
||||
textBoundaries.push({ start, end, index });
|
||||
});
|
||||
|
||||
const lowerCumulative = cumulativeText.toLowerCase();
|
||||
let searchIndex = lowerCumulative.indexOf(normalizedSearch);
|
||||
|
||||
while (searchIndex !== -1) {
|
||||
const endIndex = searchIndex + normalizedSearch.length;
|
||||
|
||||
textBoundaries.forEach(boundary => {
|
||||
if (
|
||||
(boundary.start <= searchIndex && searchIndex < boundary.end) || // Search starts in this item
|
||||
(boundary.start < endIndex && endIndex <= boundary.end) || // Search ends in this item
|
||||
(searchIndex <= boundary.start && boundary.end <= endIndex) // This item is completely within search
|
||||
textItems.forEach((e, i) => {
|
||||
for (const s of highlight
|
||||
.filter((h) => h.page === pageNumber)
|
||||
.map((h) => h.text)) {
|
||||
if (s.split(" ")[0] === e.text) {
|
||||
if (
|
||||
s.split(" ").reduce((prev, curr, j) => {
|
||||
return prev && curr === textItems[i + j].text;
|
||||
}, true)
|
||||
) {
|
||||
for (
|
||||
let k = textItems[i].i;
|
||||
k < textItems[i + s.split(" ").length]?.i ||
|
||||
k < textItems[i + s.split(" ").length - 1]?.i;
|
||||
k++
|
||||
) {
|
||||
if (!positions.includes(boundary.index)) {
|
||||
positions.push(boundary.index);
|
||||
}
|
||||
tmpPos.push(textContent[k].posKey);
|
||||
}
|
||||
});
|
||||
searchIndex = lowerCumulative.indexOf(normalizedSearch, searchIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return positions.sort((a, b) => a - b);
|
||||
};
|
||||
highlight
|
||||
.filter(h => h.page === pageNumber)
|
||||
.forEach(highlightItem => {
|
||||
const positions = findTextPositions(highlightItem.text);
|
||||
positions.forEach(pos => {
|
||||
if (pos >= 0 && pos < textContent.length) {
|
||||
tmpPos.push(textContent[pos].posKey);
|
||||
|
||||
if (focusHighlight?.page === pageNumber) {
|
||||
if (focusHighlight.text.split(" ")[0] === e.text) {
|
||||
if (
|
||||
focusHighlight.text.split(" ").reduce((prev, curr, j) => {
|
||||
return prev && curr === textItems[i + j].text;
|
||||
}, true)
|
||||
) {
|
||||
for (
|
||||
let k = textItems[i].i;
|
||||
k < textItems[i + focusHighlight.text.split(" ").length]?.i ||
|
||||
k < textItems[i + focusHighlight.text.split(" ").length - 1]?.i;
|
||||
k++
|
||||
) {
|
||||
tmpPosHighlight.push(textContent[k].posKey);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (focusHighlight?.page === pageNumber && focusHighlight.text) {
|
||||
const positions = findTextPositions(focusHighlight.text);
|
||||
|
||||
positions.forEach(pos => {
|
||||
if (pos >= 0 && pos < textContent.length) {
|
||||
tmpPosHighlight.push(textContent[pos].posKey);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
setPosHighlight([...new Set(tmpPos)]);
|
||||
setPosHighlightFocus([...new Set(tmpPosHighlight)]);
|
||||
}
|
||||
});
|
||||
setPosHighlight(tmpPos);
|
||||
setPosHighlightFocus(tmpPosHighlight);
|
||||
}, [highlight, focusHighlight, pageNumber, textContent]);
|
||||
|
||||
const onGetTextSuccess: OnGetTextSuccess = useCallback((fullText) => {
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ function ExtractedResultsPage() {
|
|||
const [customValue, setCustomValue] = useState("");
|
||||
const [customPage, setCustomPage] = useState("");
|
||||
const [editingCustomPage, setEditingCustomPage] = useState(false);
|
||||
const [focusHighlightOverride, setFocusHighlightOverride] = useState<{ page: number; text: string } | null>(null);
|
||||
|
||||
const originalValue = kpiValues[0]?.entity || "";
|
||||
const originalPage = kpiValues[0]?.page || 0;
|
||||
|
|
@ -103,11 +102,6 @@ function ExtractedResultsPage() {
|
|||
// Um zu prüfen, ob der Wert nur aus Leerzeichen besteht
|
||||
const isSelectedValueEmpty = selectedIndex === -1 ? customValue.trim() === "" : !selectedValue;
|
||||
|
||||
const focusHighlight = focusHighlightOverride || {
|
||||
page: groupedKpiValues.at(selectedIndex)?.pages[0] || -1,
|
||||
text: groupedKpiValues.at(selectedIndex)?.entity || "",
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const valueChanged = selectedValue !== originalValue;
|
||||
const pageChanged = selectedPage !== originalPage;
|
||||
|
|
@ -165,14 +159,12 @@ function ExtractedResultsPage() {
|
|||
const value = event.target.value;
|
||||
if (value === "custom") {
|
||||
setSelectedIndex(-1);
|
||||
setFocusHighlightOverride(null);
|
||||
} else {
|
||||
const index = Number.parseInt(value);
|
||||
setSelectedIndex(index);
|
||||
setCurrentPage(groupedKpiValues[index].pages[0]);
|
||||
setCustomValue("");
|
||||
setCustomPage("");
|
||||
setFocusHighlightOverride(null);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -182,8 +174,7 @@ function ExtractedResultsPage() {
|
|||
const value = event.target.value;
|
||||
setCustomValue(value);
|
||||
setSelectedIndex(-1);
|
||||
setFocusHighlightOverride(null);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCustomPageChange = (
|
||||
event: React.ChangeEvent<HTMLInputElement>,
|
||||
|
|
@ -200,15 +191,6 @@ function ExtractedResultsPage() {
|
|||
setSelectedIndex(index);
|
||||
setCustomValue("");
|
||||
setCustomPage("");
|
||||
setFocusHighlightOverride(null);
|
||||
};
|
||||
|
||||
const handlePageClick = (page: number, entity: string) => {
|
||||
setCurrentPage(page);
|
||||
setFocusHighlightOverride({
|
||||
page: page,
|
||||
text: entity,
|
||||
});
|
||||
};
|
||||
|
||||
const handleBackClick = () => {
|
||||
|
|
@ -343,7 +325,7 @@ function ExtractedResultsPage() {
|
|||
component="button"
|
||||
onClick={(e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
handlePageClick(page, item.entity);
|
||||
setCurrentPage(page);
|
||||
}}
|
||||
sx={{ cursor: "pointer", ml: i > 0 ? 1 : 0 }}
|
||||
>
|
||||
|
|
@ -369,7 +351,6 @@ function ExtractedResultsPage() {
|
|||
}}
|
||||
onClick={() => {
|
||||
setSelectedIndex(-1);
|
||||
setFocusHighlightOverride(null);
|
||||
}}
|
||||
>
|
||||
<Radio
|
||||
|
|
@ -498,7 +479,10 @@ function ExtractedResultsPage() {
|
|||
highlight={groupedKpiValues
|
||||
.map((k) => k.pages.map((page: number) => ({ page, text: k.entity })))
|
||||
.reduce((acc, val) => acc.concat(val), [])}
|
||||
focusHighlight={focusHighlight}
|
||||
focusHighlight={{
|
||||
page: groupedKpiValues.at(selectedIndex)?.pages[0] || -1,
|
||||
text: groupedKpiValues.at(selectedIndex)?.entity || "",
|
||||
}}
|
||||
/>
|
||||
</Paper>
|
||||
<Box mt={2} display="flex" justifyContent="flex-end" gap={2}>
|
||||
|
|
|
|||
Loading…
Reference in New Issue