u
This commit is contained in:
@@ -28,4 +28,10 @@ export const shipment = {
|
|||||||
return http(`/api/shipment/${id}`, { method: 'DELETE' });
|
return http(`/api/shipment/${id}`, { method: 'DELETE' });
|
||||||
},
|
},
|
||||||
// #endregion
|
// #endregion
|
||||||
|
|
||||||
|
// #region DELETE /api/shipment/:id/file/:fileId — deleteFile
|
||||||
|
deleteFile(id, fileId) {
|
||||||
|
return http(`/api/shipment/${id}/file/${fileId}`, { method: 'DELETE' });
|
||||||
|
},
|
||||||
|
// #endregion
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';
|
|||||||
import SyncIcon from '@mui/icons-material/Sync';
|
import SyncIcon from '@mui/icons-material/Sync';
|
||||||
import DeleteOutlineOutlinedIcon from '@mui/icons-material/DeleteOutlineOutlined';
|
import DeleteOutlineOutlinedIcon from '@mui/icons-material/DeleteOutlineOutlined';
|
||||||
import { tileBaseSx, TILE_SIZE } from 'dashgui/tiles';
|
import { tileBaseSx, TILE_SIZE } from 'dashgui/tiles';
|
||||||
|
import SkeleHashImage from '../settings/SkeleHashImage';
|
||||||
import { generateTextThumbnail } from '../../utils/textThumbnail';
|
import { generateTextThumbnail } from '../../utils/textThumbnail';
|
||||||
import { notifyErrorMessage } from '../../utils/notify';
|
import { notifyErrorMessage } from '../../utils/notify';
|
||||||
import {
|
import {
|
||||||
@@ -164,6 +165,11 @@ export class Attachment extends PureComponent {
|
|||||||
display: 'block',
|
display: 'block',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
) : attachment?.skeledash ? (
|
||||||
|
<SkeleHashImage
|
||||||
|
hash={attachment.skeledash}
|
||||||
|
sx={{ width: '100%', height: '100%', objectFit: 'contain' }}
|
||||||
|
/>
|
||||||
) : isText ? (
|
) : isText ? (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
|
|||||||
@@ -9,12 +9,14 @@ import Typography from '@mui/material/Typography';
|
|||||||
import Skeleton from '@mui/material/Skeleton';
|
import Skeleton from '@mui/material/Skeleton';
|
||||||
import Tooltip from '@mui/material/Tooltip';
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined';
|
import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined';
|
||||||
|
import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf';
|
||||||
import ViewModuleIcon from '@mui/icons-material/ViewModule';
|
import ViewModuleIcon from '@mui/icons-material/ViewModule';
|
||||||
import { enqueueSnackbar } from 'notistack';
|
import { enqueueSnackbar } from 'notistack';
|
||||||
import SingleLineTextEdit from 'dashgui/SingleLineTextEdit';
|
import SingleLineTextEdit from 'dashgui/SingleLineTextEdit';
|
||||||
import FillSpace from 'dashgui/FillSpace';
|
import FillSpace from 'dashgui/FillSpace';
|
||||||
import { PanelTile, PanelTileGrid } from 'dashgui/panels';
|
import { PanelTile, PanelTileGrid } from 'dashgui/panels';
|
||||||
import BackendError from '../BackendError';
|
import BackendError from '../BackendError';
|
||||||
|
import SkeleHashImage from '../settings/SkeleHashImage';
|
||||||
import quoteAutomat, { CHUNK_SIZE } from '../../automats/quoteAutomat';
|
import quoteAutomat, { CHUNK_SIZE } from '../../automats/quoteAutomat';
|
||||||
import { quote as quoteApi } from '../../api';
|
import { quote as quoteApi } from '../../api';
|
||||||
import { backendErrorFrom } from '../../utils/backendError';
|
import { backendErrorFrom } from '../../utils/backendError';
|
||||||
@@ -86,6 +88,9 @@ class QuoteRow extends PureComponent {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<ListItemButton disabled divider sx={rowSx}>
|
<ListItemButton disabled divider sx={rowSx}>
|
||||||
|
<Box sx={{ width: 48, height: 24, flexShrink: 0, display: 'flex', alignItems: 'center', gap: 0.5 }}>
|
||||||
|
<Skeleton variant="rounded" width={18} height={24} />
|
||||||
|
</Box>
|
||||||
<Box sx={{ width: 120, flexShrink: 0 }}>
|
<Box sx={{ width: 120, flexShrink: 0 }}>
|
||||||
<Skeleton variant="text" width={80} height={20} />
|
<Skeleton variant="text" width={80} height={20} />
|
||||||
<Skeleton variant="text" width={50} height={16} />
|
<Skeleton variant="text" width={50} height={16} />
|
||||||
@@ -112,9 +117,79 @@ class QuoteRow extends PureComponent {
|
|||||||
const gross = quote.grossTotal != null ? Number(quote.grossTotal) : quoteGrossTotal(quote.lines);
|
const gross = quote.grossTotal != null ? Number(quote.grossTotal) : quoteGrossTotal(quote.lines);
|
||||||
const customer = quote.customerName || this.partyName(quote.entityId);
|
const customer = quote.customerName || this.partyName(quote.entityId);
|
||||||
const quantityInfo = quote.totalQuantity != null ? ` · ${quote.totalQuantity} Stück` : '';
|
const quantityInfo = quote.totalQuantity != null ? ` · ${quote.totalQuantity} Stück` : '';
|
||||||
|
const files = Array.isArray(quote.files) ? quote.files : [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListItemButton divider sx={rowSx} onClick={() => onOpen?.(quote)}>
|
<ListItemButton divider sx={rowSx} onClick={() => onOpen?.(quote)}>
|
||||||
|
{/* Document SkeleHash / PDF Previews (one small icon per file) */}
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: 48,
|
||||||
|
flexShrink: 0,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 0.5,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{files.map((file, index) => {
|
||||||
|
const fileId = file.fileId ?? file.id;
|
||||||
|
const title = file.name ? `${file.name} (Öffnen)` : 'Datei öffnen';
|
||||||
|
return (
|
||||||
|
<Tooltip key={file.id ?? fileId ?? index} title={title}>
|
||||||
|
<Box
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
if (quote.id != null && fileId != null) {
|
||||||
|
window.open(`/api/quote/${encodeURIComponent(quote.id)}/file/${encodeURIComponent(fileId)}`, '_blank');
|
||||||
|
} else {
|
||||||
|
onOpen?.(quote);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === 'Enter' || e.key === ' ') {
|
||||||
|
e.stopPropagation();
|
||||||
|
e.preventDefault();
|
||||||
|
if (quote.id != null && fileId != null) {
|
||||||
|
window.open(`/api/quote/${encodeURIComponent(quote.id)}/file/${encodeURIComponent(fileId)}`, '_blank');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
sx={{
|
||||||
|
width: 18,
|
||||||
|
height: 24,
|
||||||
|
flexShrink: 0,
|
||||||
|
borderRadius: 0.5,
|
||||||
|
overflow: 'hidden',
|
||||||
|
bgcolor: 'background.paper',
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: 'divider',
|
||||||
|
boxShadow: '0 1px 2px rgba(0,0,0,0.08)',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: 'transform 120ms ease, box-shadow 120ms ease, border-color 120ms ease',
|
||||||
|
'&:hover': {
|
||||||
|
boxShadow: '0 2px 6px rgba(0,0,0,0.22)',
|
||||||
|
borderColor: 'primary.main',
|
||||||
|
transform: 'scale(1.2)',
|
||||||
|
zIndex: 2,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{file.skeledash ? (
|
||||||
|
<SkeleHashImage hash={file.skeledash} />
|
||||||
|
) : (
|
||||||
|
<PictureAsPdfIcon sx={{ fontSize: 13, color: 'error.main' }} />
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Box sx={{ width: 120, flexShrink: 0, minWidth: 0 }}>
|
<Box sx={{ width: 120, flexShrink: 0, minWidth: 0 }}>
|
||||||
<Typography variant="body1" sx={{ fontWeight: 600, ...ellipsisSx }}>
|
<Typography variant="body1" sx={{ fontWeight: 600, ...ellipsisSx }}>
|
||||||
{quote.number}
|
{quote.number}
|
||||||
@@ -515,6 +590,7 @@ export class QuoteList extends PureComponent {
|
|||||||
userSelect: 'none',
|
userSelect: 'none',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<Box sx={{ width: 48, flexShrink: 0 }} />
|
||||||
<Box sx={{ width: 120, flexShrink: 0 }}>Nr. / Ref.</Box>
|
<Box sx={{ width: 120, flexShrink: 0 }}>Nr. / Ref.</Box>
|
||||||
<Box sx={{ width: 100, flexShrink: 0 }}>Datum</Box>
|
<Box sx={{ width: 100, flexShrink: 0 }}>Datum</Box>
|
||||||
<Box sx={{ flex: 1, minWidth: 0 }}>Kunde</Box>
|
<Box sx={{ flex: 1, minWidth: 0 }}>Kunde</Box>
|
||||||
|
|||||||
Reference in New Issue
Block a user