From 4edd417dabca461b06ceee252413493acf079c64 Mon Sep 17 00:00:00 2001 From: seb Date: Sun, 4 Oct 2026 08:18:36 +0200 Subject: [PATCH] u --- scripts/bench-avif-encode.mjs | 2 +- src/api/StorageManager.js | 2 +- src/automats/categoryAutomat.js | 3 +- src/components/article/ArticleTileTab.jsx | 1 - .../article/CategoryPickerDialog.jsx | 3 +- .../article/boxes/ArticleViewLists.jsx | 72 +++---- .../article/tabs/ArticleAttributesTab.jsx | 35 ++-- src/components/category/CategoryTree.jsx | 3 +- src/components/category/categoryRoute.js | 1 - src/components/chat/ChatDrawer.jsx | 179 ++++++++---------- src/components/chat/ChatFlowList.jsx | 15 +- src/components/manifest/Attachment.jsx | 2 +- src/components/manifest/ManifestForm.jsx | 7 +- src/components/manifest/ManifestHeader.jsx | 1 - src/components/manifest/ManifestLines.jsx | 1 - src/components/manifest/manifestConfig.js | 25 --- src/routes/kunde.jsx | 2 +- src/routes/lieferung/neu.jsx | 1 - src/utils/importArtikel.js | 6 +- 19 files changed, 141 insertions(+), 220 deletions(-) diff --git a/scripts/bench-avif-encode.mjs b/scripts/bench-avif-encode.mjs index daa1538..8b9992e 100644 --- a/scripts/bench-avif-encode.mjs +++ b/scripts/bench-avif-encode.mjs @@ -5,7 +5,7 @@ */ import { readFile } from 'node:fs/promises'; import { resolve, dirname } from 'node:path'; -import { fileURLToPath, pathToFileURL } from 'node:url'; +import { fileURLToPath } from 'node:url'; import decodeAvif, { init as initAvifDecode } from '@jsquash/avif/decode.js'; import encodeAvif, { init as initAvifEncode } from '@jsquash/avif/encode.js'; import encodeJpeg, { init as initJpegEncode } from '@jsquash/jpeg/encode.js'; diff --git a/src/api/StorageManager.js b/src/api/StorageManager.js index ca83352..968ffd4 100644 --- a/src/api/StorageManager.js +++ b/src/api/StorageManager.js @@ -798,7 +798,7 @@ export class StorageManager extends ApiClient { return requireArray(data.orders, 'orders'); } - async doSearch({ target, filter, offset, maxCount, onUpdate }) { + async doSearch({ target, onUpdate }) { const articles = await this.articleIndexPromise; const query = target.trim().toLowerCase(); const matches = articles.filter( diff --git a/src/automats/categoryAutomat.js b/src/automats/categoryAutomat.js index b13e6a9..188d8a7 100644 --- a/src/automats/categoryAutomat.js +++ b/src/automats/categoryAutomat.js @@ -5,7 +5,6 @@ import companyAutomat from './companyAutomat'; import { parseCategoryTreeResponse, normalizeCategoryNode, - getCategoryBreadcrumbs, getCategoryChildren, cleanCategorySlugPath, resolveCategoryIdFromSlugPath, @@ -94,7 +93,7 @@ function refreshLoadedCategoryViewChildren(categories) { * Get or create a per-route category view automat for the given slug and categoryId. * (Backward compatibility helper) */ -export function getOrCreateCategoryAutomat({ slugPath, categoryId }) { +export function getOrCreateCategoryAutomat({ slugPath }) { const slug = cleanCategorySlugPath(slugPath); return categoryViews.key(slug); } diff --git a/src/components/article/ArticleTileTab.jsx b/src/components/article/ArticleTileTab.jsx index 3bad37f..64a9123 100644 --- a/src/components/article/ArticleTileTab.jsx +++ b/src/components/article/ArticleTileTab.jsx @@ -3,7 +3,6 @@ import Box from '@mui/material/Box'; import IconButton from '@mui/material/IconButton'; import Tab from '@mui/material/Tab'; import Tabs from '@mui/material/Tabs'; -import AccountTreeIcon from '@mui/icons-material/AccountTree'; import CategoryIcon from '@mui/icons-material/Category'; import HistoryIcon from '@mui/icons-material/History'; import LabelIcon from '@mui/icons-material/Label'; diff --git a/src/components/article/CategoryPickerDialog.jsx b/src/components/article/CategoryPickerDialog.jsx index bc89045..62f1564 100644 --- a/src/components/article/CategoryPickerDialog.jsx +++ b/src/components/article/CategoryPickerDialog.jsx @@ -45,7 +45,7 @@ export default class CategoryPickerDialog extends PureComponent { componentDidMount() { if (this.props.categories === undefined || this.props.rootCategoryId === undefined) { this._unsub = categoryAutomat.subscribe((s) => { - this.setState((prev) => ({ + this.setState(() => ({ categories: this.props.categories ?? s.categories, rootCategoryId: this.props.rootCategoryId ?? s.rootCategoryId, })); @@ -132,7 +132,6 @@ export default class CategoryPickerDialog extends PureComponent { const dialogTitle = title || (mode === 'single' ? 'Kategorie auswählen' : 'Kategorie zuweisen'); const actionLabel = confirmLabel || (mode === 'single' ? 'Auswählen' : 'Zuweisen'); - const selectedNode = categories && selectedId != null ? categories[String(selectedId)] : null; const isAlreadyAssigned = mode !== 'single' && currentCategoryIds.some((id) => String(id) === String(selectedId)); const isSelectedDisabled = diff --git a/src/components/article/boxes/ArticleViewLists.jsx b/src/components/article/boxes/ArticleViewLists.jsx index ffe778a..8cef473 100644 --- a/src/components/article/boxes/ArticleViewLists.jsx +++ b/src/components/article/boxes/ArticleViewLists.jsx @@ -366,22 +366,20 @@ export default class ArticleViewLists extends PureComponent { const count = Math.max(1, Number(stuecklisteCount) || 1); const existingIndex = currentItems.findIndex((i) => i.sku === stuecklisteTargetArticle.sku); - let nextItems = []; - if (existingIndex >= 0) { - nextItems = currentItems.map((item, idx) => - idx === existingIndex ? { ...item, count: item.count + count } : item - ); - } else { - nextItems = [ - ...currentItems, - { - articleId: stuecklisteTargetArticle.id, - sku: stuecklisteTargetArticle.sku, - count, - sort: currentItems.length, - }, - ]; - } + const nextItems = + existingIndex >= 0 + ? currentItems.map((item, idx) => + idx === existingIndex ? { ...item, count: item.count + count } : item + ) + : [ + ...currentItems, + { + articleId: stuecklisteTargetArticle.id, + sku: stuecklisteTargetArticle.sku, + count, + sort: currentItems.length, + }, + ]; this.setState({ busy: true }); try { @@ -492,25 +490,23 @@ export default class ArticleViewLists extends PureComponent { const count = Math.max(1, Number(optionCount) || 1); const existingIndex = currentOptions.findIndex((o) => o.sku === optionTargetArticle.sku); - let nextOptions = []; - if (existingIndex >= 0) { - nextOptions = currentOptions.map((opt, idx) => - idx === existingIndex - ? { ...opt, count: opt.count + count, mandated: Boolean(optionMandated) } - : opt - ); - } else { - nextOptions = [ - ...currentOptions, - { - articleId: optionTargetArticle.id, - sku: optionTargetArticle.sku, - count, - sort: currentOptions.length, - mandated: Boolean(optionMandated), - }, - ]; - } + const nextOptions = + existingIndex >= 0 + ? currentOptions.map((opt, idx) => + idx === existingIndex + ? { ...opt, count: opt.count + count, mandated: Boolean(optionMandated) } + : opt + ) + : [ + ...currentOptions, + { + articleId: optionTargetArticle.id, + sku: optionTargetArticle.sku, + count, + sort: currentOptions.length, + mandated: Boolean(optionMandated), + }, + ]; this.setState({ busy: true }); try { @@ -1363,15 +1359,9 @@ export default class ArticleViewLists extends PureComponent { busy, activeCreatorMode, activeListTab, - selectedAttributeId, selectedChildValueId, newChildText, isCustomChildValue, - stuecklisteTargetArticle, - stuecklisteCount, - optionTargetArticle, - optionCount, - optionMandated, removeTargetChild, confirmClearType, } = this.state; diff --git a/src/components/article/tabs/ArticleAttributesTab.jsx b/src/components/article/tabs/ArticleAttributesTab.jsx index 0436332..57bce34 100644 --- a/src/components/article/tabs/ArticleAttributesTab.jsx +++ b/src/components/article/tabs/ArticleAttributesTab.jsx @@ -184,13 +184,14 @@ export default class ArticleAttributesTab extends PureComponent { return; } - let nextValues = []; - if (isExclusive) { - const others = assignedAttributes.filter((a) => a.attributeId !== targetAttr.id); - nextValues = [...others.map((a) => a.attributeValueId), targetValId]; - } else { - nextValues = [...assignedAttributes.map((a) => a.attributeValueId), targetValId]; - } + const nextValues = isExclusive + ? [ + ...assignedAttributes + .filter((a) => a.attributeId !== targetAttr.id) + .map((a) => a.attributeValueId), + targetValId, + ] + : [...assignedAttributes.map((a) => a.attributeValueId), targetValId]; this.setState({ saving: true }); try { @@ -222,19 +223,13 @@ export default class ArticleAttributesTab extends PureComponent { return; } } - let nextProps = []; - if (isExclusive) { - const existing = assignedProperties.filter((p) => p.propertyId !== propId); - nextProps = [ - ...existing.map((p) => ({ propertyId: p.propertyId, value: p.value, sort: p.sort })), - { propertyId: propId, value: val }, - ]; - } else { - nextProps = [ - ...assignedProperties.map((p) => ({ propertyId: p.propertyId, value: p.value, sort: p.sort })), - { propertyId: propId, value: val }, - ]; - } + const sourceProps = isExclusive + ? assignedProperties.filter((p) => p.propertyId !== propId) + : assignedProperties; + const nextProps = [ + ...sourceProps.map((p) => ({ propertyId: p.propertyId, value: p.value, sort: p.sort })), + { propertyId: propId, value: val }, + ]; this.setState({ saving: true }); try { diff --git a/src/components/category/CategoryTree.jsx b/src/components/category/CategoryTree.jsx index f2f3c13..6cd7054 100644 --- a/src/components/category/CategoryTree.jsx +++ b/src/components/category/CategoryTree.jsx @@ -43,7 +43,7 @@ function getMatchingAndAncestorIds(categories, query, rootCategoryId, excludeIds if (!categories || !query.trim()) return matches; const q = query.trim().toLowerCase(); - for (const [idStr, node] of Object.entries(categories)) { + for (const node of Object.values(categories)) { if (excludeIds.some((id) => String(id) === String(node.id))) continue; const label = categoryDisplayName(node.name, node.id, rootCategoryId).toLowerCase(); if (label.includes(q)) { @@ -580,7 +580,6 @@ export default class CategoryTree extends PureComponent { addCategoryName, isSubmitting, renameDialogOpen, - renameNode, renameValue, deleteDialogOpen, deleteNode, diff --git a/src/components/category/categoryRoute.js b/src/components/category/categoryRoute.js index 3d88ca8..900c395 100644 --- a/src/components/category/categoryRoute.js +++ b/src/components/category/categoryRoute.js @@ -2,7 +2,6 @@ import { ROOT_CATEGORY_NAME, categorySlug, getCategoryBreadcrumbs, - getCategoryChildren, } from '../../utils/categoryUtils'; export { ROOT_CATEGORY_NAME, categorySlug }; diff --git a/src/components/chat/ChatDrawer.jsx b/src/components/chat/ChatDrawer.jsx index ac2f753..2dcbdfa 100644 --- a/src/components/chat/ChatDrawer.jsx +++ b/src/components/chat/ChatDrawer.jsx @@ -9,7 +9,6 @@ import MenuItem from '@mui/material/MenuItem'; import Select from '@mui/material/Select'; import FormControl from '@mui/material/FormControl'; import InputLabel from '@mui/material/InputLabel'; -import Chip from '@mui/material/Chip'; import CircularProgress from '@mui/material/CircularProgress'; import CloseRoundedIcon from '@mui/icons-material/CloseRounded'; import SendRoundedIcon from '@mui/icons-material/SendRounded'; @@ -231,7 +230,6 @@ export default class ChatDrawer extends PureComponent { const { conversations, selectedConversationId, - sseStatus, loadingConversations, } = this.state; @@ -249,21 +247,8 @@ export default class ChatDrawer extends PureComponent { }} > - - - - + + KI-Assistent @@ -275,80 +260,82 @@ export default class ChatDrawer extends PureComponent { {/* Conversation Selector Bar */} - - - Konversation - { + const conv = conversations.find((c) => c.id === selectedId); + if (!conv) return ''; + return ( + + + #{conv.id} + + + {conv.model || 'Standard'} + + + ); + }} + > + {conversations.map((c) => ( + + + + #{c.id} + + + {c.model || 'Standard'} + + + + ))} + + + + this.handleDeleteConversation(e, selectedConversationId)} + aria-label="Konversation löschen" + sx={{ + borderRadius: 2, + border: 1, + borderColor: 'divider', + p: 0.9, + flexShrink: 0, }} > - {conversations.map((c) => ( - - - - #{c.id} - - - {c.model || 'Standard'} - - - - ))} - - + + - this.handleDeleteConversation(e, selectedConversationId)} - aria-label="Konversation löschen" - sx={{ - borderRadius: 2, - border: 1, - borderColor: 'divider', - p: 0.9, - flexShrink: 0, - }} - > - - - - - - - + + + + + )} ); } @@ -362,7 +349,6 @@ export default class ChatDrawer extends PureComponent { messages, streamingText, loadingConversations, - loadingMessages, model, } = this.state; @@ -391,20 +377,7 @@ export default class ChatDrawer extends PureComponent { gap: 2, }} > - - - + Willkommen im Chat diff --git a/src/components/chat/ChatFlowList.jsx b/src/components/chat/ChatFlowList.jsx index 3831395..1b08f2f 100644 --- a/src/components/chat/ChatFlowList.jsx +++ b/src/components/chat/ChatFlowList.jsx @@ -177,14 +177,17 @@ function MessageRow({ msg, showTime = true }) { bodyLength = textContent.length; } - let displayText = ''; - if (resObj && ('answer' in resObj || 'content' in resObj) && ('tool_call_id' in resObj) && !('status' in resObj)) { - displayText = resObj.answer || resObj.content || ''; - } else { - displayText = statusText + const isToolAnswer = + Boolean(resObj) && + ('answer' in resObj || 'content' in resObj) && + 'tool_call_id' in resObj && + !('status' in resObj); + + const displayText = isToolAnswer + ? resObj.answer || resObj.content || '' + : statusText ? `${statusText}${bodyLength != null ? ` · ${bodyLength} byte` : ''}` : (bodyLength != null ? `${bodyLength} byte` : String(textContent)); - } return ( diff --git a/src/components/manifest/Attachment.jsx b/src/components/manifest/Attachment.jsx index 38aed64..e8e894f 100644 --- a/src/components/manifest/Attachment.jsx +++ b/src/components/manifest/Attachment.jsx @@ -68,7 +68,7 @@ export class Attachment extends PureComponent { } }; - handleTileClick = (e) => { + handleTileClick = () => { const { attachment, onClick } = this.props; if (onClick && attachment) { onClick(attachment); diff --git a/src/components/manifest/ManifestForm.jsx b/src/components/manifest/ManifestForm.jsx index 0a77280..7842469 100644 --- a/src/components/manifest/ManifestForm.jsx +++ b/src/components/manifest/ManifestForm.jsx @@ -1,12 +1,9 @@ import { PureComponent } from 'react'; import Box from '@mui/material/Box'; -import Button from '@mui/material/Button'; import CircularProgress from '@mui/material/CircularProgress'; -import Typography from '@mui/material/Typography'; import { enqueueSnackbar } from 'notistack'; import BackendError from '../BackendError'; -import { PageTitleRight } from '../PageLayout'; -import { PanelTile, PanelTileGrid } from 'dashgui/panels'; +import { PanelTileGrid } from 'dashgui/panels'; import { StorageManagerContext } from '../../api/storageManagerContext'; import { requireArray, requireDefined, requireObject } from '../../utils/apiShape'; import { backendErrorFrom } from '../../utils/backendError'; @@ -435,7 +432,7 @@ class ManifestForm extends PureComponent { } render() { - const { kind, mode } = this.props; + const { kind } = this.props; const cfg = this.cfg; const { status, diff --git a/src/components/manifest/ManifestHeader.jsx b/src/components/manifest/ManifestHeader.jsx index 57dcd80..c0ccbe6 100644 --- a/src/components/manifest/ManifestHeader.jsx +++ b/src/components/manifest/ManifestHeader.jsx @@ -85,7 +85,6 @@ class ManifestHeader extends PureComponent { saving, pdfUploading, attachments, - lines, onPdfUpload, onPdfRescan, onPdfDelete, diff --git a/src/components/manifest/ManifestLines.jsx b/src/components/manifest/ManifestLines.jsx index 8d50a81..93611d6 100644 --- a/src/components/manifest/ManifestLines.jsx +++ b/src/components/manifest/ManifestLines.jsx @@ -24,7 +24,6 @@ class ManifestLines extends PureComponent { onAddLine, onRemoveLine, onRemoveAllLines, - onSave, columns = LINE_COLUMNS, supplierArticlesMap = {}, supplierArticlesByLineKey = {}, diff --git a/src/components/manifest/manifestConfig.js b/src/components/manifest/manifestConfig.js index d376437..2d89fbc 100644 --- a/src/components/manifest/manifestConfig.js +++ b/src/components/manifest/manifestConfig.js @@ -275,31 +275,6 @@ function fileToBase64(file) { }); } -/** - * Convert base64 string to Blob - * @param {string} base64 - * @param {string} mimeType - * @returns {Blob} - */ -function base64ToBlob(base64, mimeType) { - const clean = base64.includes(',') ? base64.split(',')[1] : base64; - const byteCharacters = atob(clean); - const byteArrays = []; - const sliceSize = 512; - - for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { - const slice = byteCharacters.slice(offset, offset + sliceSize); - const byteNumbers = new Array(slice.length); - for (let i = 0; i < slice.length; i++) { - byteNumbers[i] = byteCharacters.charCodeAt(i); - } - const byteArray = new Uint8Array(byteNumbers); - byteArrays.push(byteArray); - } - - return new Blob(byteArrays, { type: mimeType }); -} - /** * Restore attachments from API response * @param {Array<{id: number, fileId?: number, manifestId?: number, mimetype: string, name: string, thumbavif?: any, size: number, created?: string, meta?: object}>} apiFiles diff --git a/src/routes/kunde.jsx b/src/routes/kunde.jsx index 507172d..b5b4cfb 100644 --- a/src/routes/kunde.jsx +++ b/src/routes/kunde.jsx @@ -105,7 +105,7 @@ class KundeListePage extends PureComponent { } render() { - const { status, error, entities, groupsById, busyId } = this.state; + const { status, error, entities, busyId } = this.state; if (status === 'failed') { return ; diff --git a/src/routes/lieferung/neu.jsx b/src/routes/lieferung/neu.jsx index c9044bc..b6cc5ac 100644 --- a/src/routes/lieferung/neu.jsx +++ b/src/routes/lieferung/neu.jsx @@ -21,7 +21,6 @@ import { enqueueSnackbar } from 'notistack'; import { PanelTile, PanelTileGrid } from 'dashgui/panels'; import BackendError from '../../components/BackendError'; import withNavigate from '../../components/withNavigate'; -import { PageTitleRight } from '../../components/PageLayout'; import { ManifestHeader, ManifestLines, diff --git a/src/utils/importArtikel.js b/src/utils/importArtikel.js index 529fe1b..2a18872 100644 --- a/src/utils/importArtikel.js +++ b/src/utils/importArtikel.js @@ -16,10 +16,7 @@ * only as a de-duplication / reference key, not as the SKU. */ -import { - parseImportCsv, - parseCategoryPath, -} from './importArtikelCsv'; +import { parseImportCsv } from './importArtikelCsv'; import { article, category, brand } from '../api'; import { requireObject, @@ -27,7 +24,6 @@ import { } from './apiShape'; function logImport(message) { - // eslint-disable-next-line no-console console.log(`[import] ${message}`); }