From 5dd45916b83d022f762ccbf45fa9e7dc31d4cdc3 Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 23 Oct 2026 22:40:28 +0200 Subject: [PATCH] u --- .agents/skills/backend/SKILL.md | 4 +- package-lock.json | 570 ++++----- package.json | 5 +- src/api/article.js | 14 +- src/automats/articleDetailAutomat.js | 80 +- src/automats/index.js | 2 +- .../article/tabs/ArticleHistoryTab.jsx | 1070 +++++++++++++---- src/index.css | 3 - 8 files changed, 1175 insertions(+), 573 deletions(-) diff --git a/.agents/skills/backend/SKILL.md b/.agents/skills/backend/SKILL.md index 29f2bb3..8f27472 100644 --- a/.agents/skills/backend/SKILL.md +++ b/.agents/skills/backend/SKILL.md @@ -257,8 +257,8 @@ _none_ - Params: `sku: str, body: { eans: str[] }` - Returns: `204 void` #### Get article history by SKU — `GET /article/{sku}/history` -- Params: `sku: str, query: limit?: int` -- Returns: `200 { history: { id: int, date: str, text: str }[], truncated: bool }` +- Params: `sku: str, query: offset?: int, limit?: int, search?: str, seekMonths?: int` +- Returns: `200 { history: { id: int, date: str, text: str }[], total: int, unfilteredTotal: int, offset: int, limit: int }` #### Add article image — `POST /article/{sku}/image` - Params: `sku: str, image/avif` - Returns: `201 { image: { picId: int, sort: int, full: { w: int, h: int, size: int }, thumb: { w: int, h: int }, hash: str, thumbHash: str } }` diff --git a/package-lock.json b/package-lock.json index 67fb152..1aed43b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,8 +23,6 @@ "@mui/material": "^9.5.0", "@shopify/draggable": "^1.2.1", "@uiw/react-codemirror": "^4.25.12", - "ag-grid-community": "^36.2.0", - "ag-grid-react": "^36.2.0", "dashgui": "file:../dashgui", "flexsearch": "^0.8.212", "jsbarcode": "^3.12.3", @@ -35,9 +33,8 @@ "react-canvas-label-editor": "github:sebseb7/react-canvas-label-editor", "react-dom": "^19.3.1", "react-router-dom": "^7.18.4", - "react-virtual-aggridautomat": "file:../react-virtual-aggridautomat", "react-window": "^2.3.4", - "skelehash-wasm": "^0.1.0", + "skelehash-wasm": "file:../skelehash-wasm", "sortablejs": "^1.15.7", "thumbhash": "^0.1.1" }, @@ -95,32 +92,11 @@ "react-dom": "^19.0.0" } }, - "../react-virtual-aggridautomat": { - "version": "0.0.0", - "license": "0BSD", - "dependencies": { - "@types/prismjs": "^1.26.6", - "ag-grid-community": "^36.2.0", - "ag-grid-react": "^36.2.0", - "marked": "^18.0.14", - "prismjs": "^1.30.0", - "react": "^19.3.0", - "react-automat": "file:../automat", - "react-dom": "^19.3.0" - }, + "../skelehash-wasm": { + "version": "0.1.0", + "license": "MIT", "devDependencies": { - "@eslint/js": "^10.0.1", - "@types/node": "^26.6.4", - "@types/react": "^19.3.0", - "@types/react-dom": "^19.3.0", - "@vitejs/plugin-react": "^6.1.2", - "eslint": "^10.12.0", - "eslint-plugin-react-hooks": "^7.1.1", - "eslint-plugin-react-refresh": "^0.5.7", - "globals": "^17.13.0", - "typescript": "~7.0.2", - "typescript-eslint": "^8.71.0", - "vite": "^8.3.2" + "sharp": "^0.35.5" } }, "node_modules/@babel/code-frame": { @@ -1686,9 +1662,9 @@ } }, "node_modules/@codemirror/autocomplete": { - "version": "6.20.3", - "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.3.tgz", - "integrity": "sha512-tlosUqb+3BbxCxZdu4tKeRghPFC+QM7q4X5YhKV2eCmPG+1r2F3f4AaSz5sCrFqUtX4Jh20VFTKecl16MgiV9g==", + "version": "6.20.4", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.4.tgz", + "integrity": "sha512-yF8RhOf2SXlg00+qtupzLhrglcas61boqaONiNcbPIebHCpJocpqTBA6dyrtUrQO47hqyTdeob/3XnYilT7TaQ==", "license": "MIT", "dependencies": { "@codemirror/language": "^6.0.0", @@ -1872,9 +1848,9 @@ } }, "node_modules/@codemirror/view": { - "version": "6.43.14", - "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.14.tgz", - "integrity": "sha512-hC45YnmJNR1rz42OF57BLoQNFMV12/13drnvibDsR2quNDmldcb4WvYVV81hFQg56i9lcqQMEDqilhX2QDcGQQ==", + "version": "6.43.15", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.43.15.tgz", + "integrity": "sha512-HHsfpqFeHyXLs983pSRe38Xajs0vFWZQ2BuX0m7Ki8w3jZ5iD8cuR3lBz2/5/X53Dhf32SBHKh6rtSTB6tKeGw==", "license": "MIT", "dependencies": { "@codemirror/state": "^6.7.0", @@ -2168,9 +2144,9 @@ } }, "node_modules/@hpcc-js/wasm-graphviz": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/@hpcc-js/wasm-graphviz/-/wasm-graphviz-1.29.2.tgz", - "integrity": "sha512-AkArBAZERT5OxH52/+kvCHB07cZ6ZNd9GnOvjw+S880bR88D6i27XfK6xj4dBhUDxNA2QPPMdgEcky3x4TJ3KA==", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/@hpcc-js/wasm-graphviz/-/wasm-graphviz-1.30.0.tgz", + "integrity": "sha512-T20IKosOZuex2qV049fQokVJy2MWv8w9Md5V/4mRKCXDf49fBCR50VD1yBlPYHaQlHPsFGRdqXN//r59vZliWQ==", "dev": true, "license": "Apache-2.0" }, @@ -2895,9 +2871,9 @@ "license": "MIT" }, "node_modules/@lezer/common": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.3.tgz", - "integrity": "sha512-H0iErY4e43LpXbYDyBci5W4v/RwTgGV3YzYOlJPiGZ8RY8w51kVE+xLn1tg3Z6UmSfyETvtsUK3r7YsgDQEI7Q==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.4.tgz", + "integrity": "sha512-xt3Q4z64xM+xhg4M7NXqw1N//1O74bUFo5kz6fwMeC4qwxSuRdwkYSmjcqCEEKYkNw5e67f2hcNqBoNERAEU0w==", "license": "MIT" }, "node_modules/@lezer/css": { @@ -2963,9 +2939,9 @@ } }, "node_modules/@lezer/markdown": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.8.0.tgz", - "integrity": "sha512-X6w3A2NpyhdtGqTWRJB8gR4QDXBaFMbTOs780ZdZ15KKCfBXOQTKcB3Vr+W6tqJHVlealt53tLmHRvOqPTQgYA==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.8.1.tgz", + "integrity": "sha512-M5YmEcKWO4mJ45Y1hECwqyu8cLv25EiXOK554PVOvDOWOP0olwelHHQUWr9sjF+d1bENVhy0nfJ8E57XZUTiXg==", "license": "MIT", "dependencies": { "@lezer/common": "^1.5.0", @@ -3243,9 +3219,9 @@ } }, "node_modules/@oxc-project/types": { - "version": "0.154.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.154.0.tgz", - "integrity": "sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==", + "version": "0.155.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.155.0.tgz", + "integrity": "sha512-SeE8JPwW1xs1tHeNycjUtUBdhorRa8o4jlvjwk49R7/Z291i+4DQa7JJIgOm/TaYQZx+QrPQbVJ/9c8dMIZN8Q==", "dev": true, "license": "MIT", "funding": { @@ -3263,9 +3239,9 @@ } }, "node_modules/@rolldown/binding-android-arm-eabi": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.14.tgz", - "integrity": "sha512-aWR+XKH9+rW7m5fWq/5360J3mHycrx/o6xZM2DQFdJnTMdyP7/WzxPjhtLbVWdKo2y612/4U1bWqb3HQhiF7vg==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.15.tgz", + "integrity": "sha512-aLcgK9gIJ3YRvrrtfSBbRa27F5WrpiTaPulnFpsHPxpUHgFlSgnU4854MHwoRGEBhfRJDWCS2WQ7lIjskE9Olw==", "cpu": [ "arm" ], @@ -3280,9 +3256,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.14.tgz", - "integrity": "sha512-QiVxHofl6A8lQU7WAtOUY4QMVZXohxwz7WJJoeh8NBEUyKfIkMRKhYyq8az/1RypNiIXzNTtiS6KwHz0erxYRQ==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.15.tgz", + "integrity": "sha512-xD7DdZCrbThKuxNg7ooQmvp07ys4J/pnSEMTG3/OdOWl6daC67m/Q4fL78sRHMxTH/N4fGUbYhcPM0MF5WFHkg==", "cpu": [ "arm64" ], @@ -3297,9 +3273,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.14.tgz", - "integrity": "sha512-lTQOzHuBIooh3jIr5XINQkjPGEuGy+Dsy0meXDr6Sjty0b99kYgGh4uBC/8mJX1T0kC8d6S0aPP1Y+bHkh6aBw==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.15.tgz", + "integrity": "sha512-m2WuQ6r0B4OTYxyPpNLtXaMRbRDUbG8YQV2Q3KTdSSK8Th6KHCnC8jVCJt8bvYeSB5WivkkNbc85mKadaSdOxA==", "cpu": [ "arm64" ], @@ -3314,9 +3290,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.14.tgz", - "integrity": "sha512-hyMKEGatjmBYCs/Q4sbIcL/GqpFEqsX3wc+HYVQ/85A4rxc1o7rPm4DUI4GV4k/h0ITddwFSGpqQunI14GXjTA==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.15.tgz", + "integrity": "sha512-5RtnsHM36nodM9WbMy+zip0LGS/G+y5wro5RHrpOlr4ac24+1zSi9kiV2MP1myZeZ/ifEHfulQcWjnAXzc2C2A==", "cpu": [ "x64" ], @@ -3331,9 +3307,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.14.tgz", - "integrity": "sha512-u371GbXoVXrEgP20PwzoGNOdAOqAMhzo19JzzY+V4YmmnC+DTOoqdbMu+O+54emM59Mik/UdrtWgcuEDKWRPKA==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.15.tgz", + "integrity": "sha512-g3l09pyFqhu+135JKkbkwiKGQmwU5hUMUPJ4VdBADvuqR8d33L6H578rh8m7rtxbdp+VmX/+nzI7nvhSZlzpUQ==", "cpu": [ "x64" ], @@ -3348,9 +3324,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.14.tgz", - "integrity": "sha512-BqwKsdZQf6EqVWr8fv2MrDYzAvOZ7+NYFSJESRGs87fkseEhs0TU9TXgRJTkZoRRkxTizyEg1LKUXfU3/78uqg==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.15.tgz", + "integrity": "sha512-nIe3VugI97nGQtspPxDqA4sXMUpeiocKIP/CqpY/u/vgbT+alX+cVxu1C/oVBPKg4feNTmYovE91v4DgXvXNwQ==", "cpu": [ "arm" ], @@ -3365,9 +3341,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.14.tgz", - "integrity": "sha512-SD9kY8M009x/7s57Z1dgUVlP5+uYBgKQK0Tkr1WIWngrtUJmRCW1RJFMY7QDla2khXhmg2i5Io7MUjcmZNZ/KQ==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.15.tgz", + "integrity": "sha512-iTBjXx+B5QSvgI89lJfmqh4wTh8NabR1YZIIN3hNx4zSG0EVfVqkOvLulNpG4251pbd6/IAmZ/LefVk1Y4rPhw==", "cpu": [ "arm64" ], @@ -3385,9 +3361,9 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.14.tgz", - "integrity": "sha512-BJ2CL19M6uuWesMgnqJzgxoI+N+eV7b0A9O9vLV42y+gitC41fNa8KElau1tHVzuLWX5GzEuxMPhAO0tQXQMkg==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.15.tgz", + "integrity": "sha512-uN26XOnVR7rqQupG3V9oAG2EGGatWjcJHOeDOHUFCh4TBWmP2tHTFoVN13aYbwfm0aHqJAEmcwhAu6sooIjfqQ==", "cpu": [ "arm64" ], @@ -3405,9 +3381,9 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.14.tgz", - "integrity": "sha512-4+Kl8daPV8NDHaD7mfCcc1pRM+Qg7ab8DyMm5FG5WoZgv4h2i3KFN1CybYBNbQqmuYm7ftJLvmMI1eHYJ22S/Q==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.15.tgz", + "integrity": "sha512-9nWkcdd+H+XhaA3fQIwpHnKIrfx/PQ6rO0pivr78Og07tXlUlctBBJoEYLPfhTmCR/QxEVdn6uPjHV5SymPhdw==", "cpu": [ "ppc64" ], @@ -3425,9 +3401,9 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.14.tgz", - "integrity": "sha512-V/h8ePq1fKDrmtFMz6xcCN3DKvuvMRrwwD1q0PkBeeo4DpK64biaKvqWGVxqCeYKqeRk7gE7/iKPxLCn08O97A==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.15.tgz", + "integrity": "sha512-Ggh0ciFjLwIusLSLz7LZYEaGdxOAUJXI+Qu5JCbhPJJHEt8vP+IjRATTJheiJsdzzTYgUiHUiw3X1Ea3ZpMBdA==", "cpu": [ "s390x" ], @@ -3445,9 +3421,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.14.tgz", - "integrity": "sha512-WxalXzgrLVpKC93xfpaJ3gCXUWzeCr+FRCbDVD2mUAy4L6Vo3lNVz0epUEUpxPWJkLNYUwM4OSIikv36OJ9mLg==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.15.tgz", + "integrity": "sha512-FHg60rS6DBePAYZ9X9F67x+JObFdmgn6tupA1C/a3B+CufFmTD4mX+e8M75tCiAO3foR/6xwVBI0KQiI7sn/rw==", "cpu": [ "x64" ], @@ -3465,9 +3441,9 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.14.tgz", - "integrity": "sha512-3G3tnAmTpdk9jO3GQtyHXqeFD2SlecfTws/Y3M2mmj9nMBwwuLT4kur8sZKeu7ENUHSpVO3cIsm5A52LEWWwlg==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.15.tgz", + "integrity": "sha512-/cvV/7v5VGz/moiz0XKRj2dE8DzsKyhIu1KpOvJGPjRywg3yscON889UGvAe8zfiJLHup7VLjBduoGWi3HusWQ==", "cpu": [ "x64" ], @@ -3485,9 +3461,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.14.tgz", - "integrity": "sha512-qyr5XiNGxm2ytx17vvtcJ9nXn6v1gENETi503bJx3OGwZ1tSonj7BosxbMa/xeAfSl5iS9X6KjEWYXLu6v1L7Q==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.15.tgz", + "integrity": "sha512-MyzC5Hrv/sm+Z7TSGKP/j8001RO2xQm1zOpCNVL4j0cY/VhBZviludA2YFQ7i4lH6ZAXxQm0lcMdBzM+99mE7w==", "cpu": [ "arm64" ], @@ -3502,9 +3478,9 @@ } }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.14.tgz", - "integrity": "sha512-oA4o5o0S2yB199YyYXDzKUv1Z56Rc+mgOjwm7Z/vJ9Z8igiDPYvoOuDyo6g7AK/ZaF09nPhDKVnGBcYHO11GXA==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.15.tgz", + "integrity": "sha512-+PgYiS+AH5omy6L45ZLxybasauJaj3M8buoT83D+nzPmCayXlxUV9hydhciCKVyIg0B/v0BtXPDE1uGqNwCPpg==", "cpu": [ "arm64" ], @@ -3519,9 +3495,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.14.tgz", - "integrity": "sha512-9mE94bf2GZUaR/fUSXCMpBoWkctu421Mi0ORpm4zqfbkjKep7RxzPFa5etcGs5h+2KApoWBOA/hAJa/7saGgEQ==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.15.tgz", + "integrity": "sha512-HFZd2QNQYn1JbIi+Hpd7H+r/lkWxcfIu28nirZ6eCn2LafuvmExMlb/P96Sfx5tf7pPArw39IdhmCF8vmV+NhQ==", "cpu": [ "x64" ], @@ -3617,15 +3593,15 @@ } }, "node_modules/@rollup/plugin-terser": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-1.0.0.tgz", - "integrity": "sha512-FnCxhTBx6bMOYQrar6C8h3scPt8/JwIzw3+AJ2K++6guogH5fYaIFia+zZuhqv0eo1RN7W1Pz630SyvLbDjhtQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-1.0.2.tgz", + "integrity": "sha512-+UihHnuLnQDQ/9wog7ym+7oawCXkjTIo0WwkK7s//0mkktTN0VhYk6fGVxH+NtGzW064w5RCGgreMDxRVhHCzw==", "dev": true, "license": "MIT", "dependencies": { "serialize-javascript": "^7.0.3", "smob": "^1.0.0", - "terser": "^5.17.4" + "terser": "^5.49.2" }, "engines": { "node": ">=20.0.0" @@ -3640,9 +3616,9 @@ } }, "node_modules/@rollup/pluginutils": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", - "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.5.1.tgz", + "integrity": "sha512-P9ZvnfouRu4MSC+ilERaw6FmZs8zqKhpHxEs4aGDGWQAMzQGXnhvCSvoNwokfNvdt7t3Y5Y4p6gStQgezeIqug==", "dev": true, "license": "MIT", "dependencies": { @@ -3663,9 +3639,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.64.7.tgz", - "integrity": "sha512-GFF2tHk0NqYVObrK0+/ps/LEXsV/v2q6Lyiy7mZr+Ej24fpQScvqK2ziz9NHeEQYnKWKym38Ml7dZbPtC9tuAw==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.65.0.tgz", + "integrity": "sha512-t2AnVba25baFdq7gczzS13JyVcdubLVbFX1X04mxrggDrTQPUXNv3XM0k9H1hr5tqvg7AVvtQ720QHAj0iYqhg==", "cpu": [ "arm" ], @@ -3677,9 +3653,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.64.7.tgz", - "integrity": "sha512-BOymcXJFYYXqluDidj6sLelNjXruC3u1BqVxLn2OPCXH9xaPSOTH+MS4uychsGI1NU7tJoiv9KvqijDHFe+hhQ==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.65.0.tgz", + "integrity": "sha512-dNONUaEwPGhl/nuO2KV8VABWlcjYyU6KtZGN8dQv5OS5JU7JSCxPijVNKXbRJd0iuTzTiJ4TjPt/4bbvDRNiMQ==", "cpu": [ "arm64" ], @@ -3691,9 +3667,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.64.7.tgz", - "integrity": "sha512-jgVpGweIbls2H5jfBB70tnX52abMd5pJr3xmtoDILx6JdmGl+Un+tMb9R+MbHPVB46tTBpY8emtn7M71SnQhEQ==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.65.0.tgz", + "integrity": "sha512-zWQqUH+9zavr2Bxuzfpuv2SIF3X31cr58TvSQC9o1GhpOvkqRwr60GkZdQcudyT/BEgdpdSafjgd2I13MbTL7g==", "cpu": [ "arm64" ], @@ -3705,9 +3681,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.64.7.tgz", - "integrity": "sha512-AVMpt94mrXH7WjyWKmd9nT4RC5yM0AN3Lt6A89xVIsuLDi3dDX6dxMytLbW36FlppY9JsoqUoS3LUUpUrYxiMQ==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.65.0.tgz", + "integrity": "sha512-RQYreBFWtO4//hIuOaZkYUnF/lPU4lz35dveDimDshWCJvVisVtJ/shmT9bkXK8wFJY+FJF89X6F3Cq1qI3LCw==", "cpu": [ "x64" ], @@ -3719,9 +3695,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.64.7.tgz", - "integrity": "sha512-Nje29c/MyajxRNFGU05oyeTDS6SWdMg/wWMSlZSBTBju5BKz2NVc0kFiFSQGzRELNiB+CBk/ZvAVsWsENgjGag==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.65.0.tgz", + "integrity": "sha512-A0NfMj6Cuh/9BE5k3awJKv6HoxFVXIcLAb6SZqAMoxUHPA1ZNNK4RsGuUPD/vL7nEAm9LG+ZzXWWTrnC0XtkpA==", "cpu": [ "arm64" ], @@ -3733,9 +3709,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.64.7.tgz", - "integrity": "sha512-xxgN5/kMzCNz/NYJ4t49B0/WS6InNlWv6xvgwUQqNnWM9WJMMwMUGWrAxdNEgYWdHL0sMnuh8I87StGrIMTA+w==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.65.0.tgz", + "integrity": "sha512-BI6/H7q3aP0I7S7GOrjyxTjgEJlSnovXE38+bdxBpuKN6z+d//uF+T+VQ3Q7ltJL/71p17ufartARX9Ja5gOGQ==", "cpu": [ "x64" ], @@ -3747,9 +3723,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.64.7.tgz", - "integrity": "sha512-5U/9gVn/X657I8+NHoHO9Wnfyd0lEXwqbslobRoB9TC8SwYzOitcIr6TLE7531Q/NWs3L4mb+YOGzlf3vHIeYw==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.65.0.tgz", + "integrity": "sha512-W1vUprf09RWaVWnsFP1vlUkEWJzTZlpObOEAYZXt9Fq0UVAOYEkeGr7wBX7McKqqIQskXdBnpiOMgwPujordgA==", "cpu": [ "arm" ], @@ -3764,9 +3740,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.64.7.tgz", - "integrity": "sha512-hcDS0a/Y8ggM3dcOfzH7UpSaogCViWTtNDSl0EXpWIj8g8/r86ITqptjil2hayTXS0Umzb+Yt3mjgpQVFVf2+A==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.65.0.tgz", + "integrity": "sha512-s8QTcZWgrl9haFzEGIqyE5BWyo89pFDGLMBFZ752WYxk8DJwNU/O1X6pZgPw829d9/sm6CCHyrMP3aurt76p1Q==", "cpu": [ "arm" ], @@ -3781,9 +3757,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.64.7.tgz", - "integrity": "sha512-awbAr4N7Qd/yjZAQBEEPzgcPveYG2Gi5L6gq1/Bp+3SMRjn5F68Wv1zKsntzvvoioBR6yKvhLtWqu11am1TsxA==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.65.0.tgz", + "integrity": "sha512-ke1f6dLRzkqveyjjF2fkEwQYZvxHtNNwjegY8nJrwcO0Bdqr8CzFO/pKE0Bns13cx0qz2Ba2Y0Hs3dSwMdnHxA==", "cpu": [ "arm64" ], @@ -3798,9 +3774,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.64.7.tgz", - "integrity": "sha512-Ut7xQJfeLhzu2yN3rHzVvL9ccyPJvN4aCdP1V7hJ5lGxX/eCzgB9SiMk/Md3J+rWWZgvoYsDW4BUFggJr32pBA==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.65.0.tgz", + "integrity": "sha512-926SMeUcy4y18Rz/w2aJiUKOnyAnm6czg72bXkQEaeemsll+Wr0hnsjb2BGRpHvWgwAMYy5ACJCotbvfLCfj0A==", "cpu": [ "arm64" ], @@ -3815,9 +3791,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.64.7.tgz", - "integrity": "sha512-trqoni/vHkuM5oo5iQhoKPh6fjjD7E80pMgCXWgGxU8vSRPUlwvG8GeYvEEcB6eJAxNa99WH9iVHPHelgtKiHA==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.65.0.tgz", + "integrity": "sha512-6T7JNRP1hc4hqF2dUsEoVLOt9K8tmODoCLldtQRYnrddGGQY8Gqe2pM/qMMUo7EMowpP7oa2N95k0/8sYK/ipw==", "cpu": [ "loong64" ], @@ -3832,9 +3808,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.64.7.tgz", - "integrity": "sha512-gvlUy0XFIwtUWiQmhc+4GT2Knm3KosinpUVhr7CtTFA78gFDnE5NWwMPzHrJsYpKkh2LlY7yvBIboN1FAV6Xeg==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.65.0.tgz", + "integrity": "sha512-SImGFl1Je5kpyAgOCPONVT7h6ASV8mAUwGRjY7eZvVjPg//PfHOXgI+P241RF/+HqsA4PP3qD527ysWFKNQyhQ==", "cpu": [ "loong64" ], @@ -3849,9 +3825,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.64.7.tgz", - "integrity": "sha512-8yS/kSXTJ/47Z62JW+C2AJ3vd/8zZw016vFjtNpZwmZlwJumLua4s1i78dkYuSSqQ+0aIMxJcBp/4uIwp2ehjA==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.65.0.tgz", + "integrity": "sha512-XeDTbmPF1Yu5asfXGPrMkWoxTDhgryQbmw5Q1+R582O51VNCk23J6f2pDrsAp5YkneBVBwtExx6ZGOb9D2aQ6A==", "cpu": [ "ppc64" ], @@ -3866,9 +3842,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.64.7.tgz", - "integrity": "sha512-mxVSKvvty0hOP1AFo/l4Kpv3i3HK0zx4rYUrirZDToYlWhS3xzmIkq3vUJ7rtrM2cPyXveDyDT6M1FfXZ9hTRA==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.65.0.tgz", + "integrity": "sha512-VS55JUI/1nsljmV/jfqNkLZXFw8uMO8nNlfoHmSevNf6fO3neuhyDvx9dv3c/Ytt8r/431SL8Qax1dpYvOMZTg==", "cpu": [ "ppc64" ], @@ -3883,9 +3859,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.64.7.tgz", - "integrity": "sha512-lEse1zra1CagM+uHH2bl28GInDsZZ45NJzHei2OMaXQFzZWKBO1hFo07rS0xB6ayV4WU360UrSmPDSyCMpYsUQ==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.65.0.tgz", + "integrity": "sha512-Vblw84TbX7RS4la1Y4+yQ7aore/oSyaNtFbppuBr5Vs/4LfBeXKq9dIfoExw6zOvRERqd2rRAjnZRaMhH/0x5w==", "cpu": [ "riscv64" ], @@ -3900,9 +3876,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.64.7.tgz", - "integrity": "sha512-d/cqCoiG9WMZ5VuJZ5Qdlv9g97QyoGwnmvHccvGhKSacTy7xFrAS+jMcJSBdMNOw1oacSkl6p7K6O/DRYTKL3g==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.65.0.tgz", + "integrity": "sha512-7+gHjtONvKgwR9InTKFaLq53f6YzBJkgeMRBENdWTsQr+spahGqQm8HF5aXpq8i4JaRrOqYyv6Zn1WltDTxaZQ==", "cpu": [ "riscv64" ], @@ -3917,9 +3893,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.64.7.tgz", - "integrity": "sha512-kVEA//CeDOZZP1XCH2JBgqXb9+ALlwuA/4civaazMVdgzaSQC9WM38w65zG/LLk0lA7F9Od19CSBZW7J9mCbNg==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.65.0.tgz", + "integrity": "sha512-KvNDC0J6s4vVHhtJ6KrDXU0Er0au/hmRIBq/+1maCV8TseGupeKizq0bWcrbp2HE1T8xoknvN0Q/KZ/YF0qX3w==", "cpu": [ "s390x" ], @@ -3934,9 +3910,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.64.7.tgz", - "integrity": "sha512-14oLfDsOSr0TSntT/34jRg/V8B2XW/Jomh9zX9CjIM9gwwNlI1OCymS/GVn0DV32h67eRf7U0GGem0rvfXgNwQ==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.65.0.tgz", + "integrity": "sha512-GExdD15WPvu/x/drELjVam7vX8EsPgvTMOa/iJL/p/4m/oOqzbb7JXZg8fXR4hlXtg/sF2zyTZ3bR0AEtEMlhQ==", "cpu": [ "x64" ], @@ -3951,9 +3927,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.64.7.tgz", - "integrity": "sha512-dFVtPfjZqAnUPpPY4Bfg+87yo1IBW9HiY8iCFtg49Pn46MfZTebSHZh8PL6SOsgyt9LQP8Nj/sE6jm3aWpySmQ==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.65.0.tgz", + "integrity": "sha512-8sT9PemIZfIMED4Vd4KGoOXVDj5CMSWNcGdbheRUx9TYS03yOWdT2Q0lXPyEyNBB9YTilwewIQKNIBk6Nxi0Kg==", "cpu": [ "x64" ], @@ -3968,9 +3944,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.64.7.tgz", - "integrity": "sha512-Dm9CZ2SM3u2NgvBj4awW/gGqkOwzH8f6MSYIJE6+bKcKLI+T0+LhpD6vtetTfrIIx+rLXDf5RJqBP6v7V5O+wg==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.65.0.tgz", + "integrity": "sha512-pO6Ehi0jo5yE0R6PltKhJhv9mlIiyzBJk5N5NUF2OF6xtVKI+1bdXxj/rb0jGXy3hck1ELVT0QPY3tzkAm360w==", "cpu": [ "x64" ], @@ -3982,9 +3958,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.64.7.tgz", - "integrity": "sha512-oaxsvS2mL6+78741CT2HCORBvy1USg3Wqpt5qvZwy3aMXRMl4zxyDo8maeFRWJkF3dp0Wbi71fKH5Gr9YI3vYA==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.65.0.tgz", + "integrity": "sha512-vo7N3/+cjjPDYr8vtxC+qSNgWa9sDvJ7g8N8R5SWqFY4WiNH1ULcAU70SKVyHeiIZOYYwNP9pTipmhN5sl1NPw==", "cpu": [ "arm64" ], @@ -3996,9 +3972,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.64.7.tgz", - "integrity": "sha512-UKZz1Y4mxUqkWh60uH7B1aZn6UcAimPk4ipRktpb3wfZq7JrzZYyAXTwiafkb3T+kd5P3Sf+vzcRdsDks4WtjQ==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.65.0.tgz", + "integrity": "sha512-ArwvgFAbjKcDM7qqotZ4OVYf+UMT9xH2YzkCzK4+AuZSDihMlz1Ekoe4INwBVXzn2mnJzuIYOcSx07iTBijGRQ==", "cpu": [ "arm64" ], @@ -4010,9 +3986,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.64.7.tgz", - "integrity": "sha512-WWkSuC1J+mZJnsDh0mRaCAFSWfQdl6y3fDjZeWElI6zHo8CcOSG5lY3yurKJjEq+FrX0WD60sFrVVpbHqzMmrw==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.65.0.tgz", + "integrity": "sha512-QGMmK4/cxKE/36FoLMSHQBCyymv/eFTnsCvvsBF0rgmOvVbvX78VWZRerL3dHa77f4pM6Xcc2iGDhJ10w/svKQ==", "cpu": [ "ia32" ], @@ -4024,9 +4000,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.64.7.tgz", - "integrity": "sha512-u9bp2yXCI3/BUjUxY6uWknAY32pfvvDCPysyUTySotx0dj3ydlFHrRQYfn/b/kZgnfjyEwySMtI7Ga054uiysQ==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.65.0.tgz", + "integrity": "sha512-XfKYFWHIPs4HPODIMsGF1IKlS3H1e3WokUZIgpmn4+uNnZBlnRDDHEylNyazbQXwhMKZre68OjtRYbKqb5+j8w==", "cpu": [ "x64" ], @@ -4038,9 +4014,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.64.7.tgz", - "integrity": "sha512-EhX6N3XPMEnVU5cRfNgzPOKcSucsbu3nNNWuoAaEuKIqmddBKHN5b9d4rPe65T1I+FaOT176JKiZNsUBp3rqbA==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.65.0.tgz", + "integrity": "sha512-wPWi++K4Bs1VR4XihOhfGi4IGX6Cub7FlerTf8X2v+2BtDHddgSqWCXwGD+h2yAe4/niIhNDwAltioOC+wEogQ==", "cpu": [ "x64" ], @@ -4245,42 +4221,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/ag-charts-types": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/ag-charts-types/-/ag-charts-types-14.2.0.tgz", - "integrity": "sha512-4pDV6/4zbzPN7t607Gr1o6DO9RhmPafQGr+hIpTJBaerbaMoC+WOO3v/wkxFbvCNrHKOexEKSfNTH7PaAR4UzA==", - "license": "MIT" - }, - "node_modules/ag-grid-community": { - "version": "36.2.0", - "resolved": "https://registry.npmjs.org/ag-grid-community/-/ag-grid-community-36.2.0.tgz", - "integrity": "sha512-tK0Toj7t0fV/OMLPnDc0xlYKAqDbnCT3iJodYSn2TJ541caU8jPdYwWhMdW+AP2+pUNwFiJVgc04eJNfvBPsWw==", - "license": "MIT", - "dependencies": { - "ag-charts-types": "14.2.0", - "ag-stack": "36.2.0" - } - }, - "node_modules/ag-grid-react": { - "version": "36.2.0", - "resolved": "https://registry.npmjs.org/ag-grid-react/-/ag-grid-react-36.2.0.tgz", - "integrity": "sha512-7dsaR4Ga8/bJAOov7XJqxsDc1JAjUU5Bmh9+s4U9+/TKIdSsaVo53SuZb2yEFSB1elv3eh6aZP8a1fqGZehXwA==", - "license": "MIT", - "dependencies": { - "ag-grid-community": "36.2.0", - "prop-types": "^15.8.1" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/ag-stack": { - "version": "36.2.0", - "resolved": "https://registry.npmjs.org/ag-stack/-/ag-stack-36.2.0.tgz", - "integrity": "sha512-f3XT2htFs9dUPcHni2z9ak69QNta5ODEpooHuuNvbjN98JkokpEqRQ9YLQHQJFdCcgi9Ybs/j3zkkvmNRamIPg==", - "license": "MIT" - }, "node_modules/ajv": { "version": "6.15.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", @@ -4492,9 +4432,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.11.29", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.29.tgz", - "integrity": "sha512-YeesxhUmR4h5y5V8KF8iBCqJb8YFrBJ++XBTeGcWIaQOYXGN19JM0FoiOjAhwuDoln8owMgXcWBmgHtYSkky2w==", + "version": "2.11.32", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.32.tgz", + "integrity": "sha512-UvuxFU9P3hM29LrQdwu0cD6w6/+SFr+UlB9s/knI7+O2rK9xFxKUwSDWxGdbbqQ9/V7BJ5s0NI5nQAE4uJp3gQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -4529,9 +4469,9 @@ } }, "node_modules/browserslist": { - "version": "4.29.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.3.tgz", - "integrity": "sha512-1R4kiYKXGViqEN0CnoDrXc1StD9niAwu+j2dukWzrD4bJgsD4lDmEp0CRbc6E/vYJIfTHwPmwyaKtVSudICdPA==", + "version": "4.29.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.29.4.tgz", + "integrity": "sha512-2TcbbiwXEq+N0kD36tykpCfyyQigUXmuwNQbnPp4Xk4PX9JOqVIKjJlIDjpH7uY6tmRGoAd+apeT1p60T8wsdA==", "dev": true, "funding": [ { @@ -4549,11 +4489,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.11.26", - "caniuse-lite": "^1.0.30001813", - "electron-to-chromium": "^1.5.439", - "node-releases": "^2.0.57", - "update-browserslist-db": "^1.3.3" + "baseline-browser-mapping": "^2.11.29", + "caniuse-lite": "^1.0.30001816", + "electron-to-chromium": "^1.5.459", + "node-releases": "^2.0.59", + "update-browserslist-db": "^1.3.4" }, "bin": { "browserslist": "cli.js" @@ -4676,9 +4616,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001816", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001816.tgz", - "integrity": "sha512-+8Yx7BXCoqk6IF8yTicjfUR6D/ldJzdlsodlEOiOSPmhK844WIgk67/zIQaGAOxNkZyyvBlrRFnLvqKIoqbAFw==", + "version": "1.0.30001819", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001819.tgz", + "integrity": "sha512-LFUqIIAwpzsIuevnKnsR9qnStBcgzPShTX61lBwN9uFkkf8o8zLiebEjbW8AYtZiF+1YKDWfdt/pWDtMuG8Xwg==", "dev": true, "funding": [ { @@ -4806,13 +4746,13 @@ } }, "node_modules/core-js-compat": { - "version": "3.50.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.50.0.tgz", - "integrity": "sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==", + "version": "3.51.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.51.0.tgz", + "integrity": "sha512-52r6fkXgxv4GLMjmFcMWRx7X9bw071xTTdrDcdyPGRqU2oE+9pCG0bAOMifSBdLw0JRBZKEF0q3B55qPlLuE8g==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.28.7" + "browserslist": "^4.29.3" }, "engines": { "node": ">=6.4.0" @@ -5102,9 +5042,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.458", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.458.tgz", - "integrity": "sha512-/hIH2gRSmxrf4/X4Nw/t/Wc8PVS22l8/3HnWjWTWsTOM5dsnMUPZF/+u+yr3LqweNuTBJE1rq6qAQzKkZVwMfA==", + "version": "1.5.464", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.464.tgz", + "integrity": "sha512-nRa65aFge40viPAKxMKULIY8tcXKwKboJWNn4RoKwyWXJ6SP7BnrDGKUTzc64818jIciH0PK7LSF8QzZes19GA==", "dev": true, "license": "ISC" }, @@ -5537,9 +5477,9 @@ "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz", - "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.9.tgz", + "integrity": "sha512-hS/0Wt3Ya043oKXs0sIxrMpKQITXhMLIrVAKKXi4gozGC9v7YRWVnXIZzjNPTO02M9BdxLCWqK1yRXgNziVyJQ==", "dev": true, "funding": [ { @@ -7275,9 +7215,9 @@ "license": "MIT" }, "node_modules/node-abi": { - "version": "3.99.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.99.0.tgz", - "integrity": "sha512-lLdwkeg2XUVPTHqWjPltTxH81zbQNbUWC+AEb9ni50KjxkUzAAx1HGtMT21sbntzfUGfIphhcklvs3imJeqDXw==", + "version": "3.101.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.101.0.tgz", + "integrity": "sha512-bkb/RkuWCE64eWu1PCh3Fu2pGc9mKRs+kOE+FU2bGHRYlQa86/D321DSATV54AsCQMKz3/xSt9sRgraZTpqdhQ==", "license": "MIT", "dependencies": { "semver": "^7.3.5" @@ -7305,9 +7245,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.59", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.59.tgz", - "integrity": "sha512-5qr2okC4ItAI0hG5SaV0HoYMpnM/Y6+Oqr7AmPYy/2uEoGvS+GbSKLeRxSS1uAdu59yz0ouzcuXievSgg///WA==", + "version": "2.0.60", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.60.tgz", + "integrity": "sha512-OmO8+GM1JUZqXET720VrJCwkjUCXmCMQm0Z3UDDRbfNLHS4NEAvY60j5jiFv0tkKw2PNNlqOLhahVmwJIOLDIQ==", "dev": true, "license": "MIT", "engines": { @@ -7628,9 +7568,9 @@ } }, "node_modules/postcss": { - "version": "8.5.30", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.30.tgz", - "integrity": "sha512-zkd+e9S1AQHhmaBKye9zlFHWjOwVgqXl1q3ECYy8561K7qxR2cREf/STLskulBFd78k6AOFeA+ff1TtEzk9bAA==", + "version": "8.5.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.31.tgz", + "integrity": "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==", "dev": true, "funding": [ { @@ -7894,14 +7834,10 @@ "react-dom": ">=16.6.0" } }, - "node_modules/react-virtual-aggridautomat": { - "resolved": "../react-virtual-aggridautomat", - "link": true - }, "node_modules/react-window": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/react-window/-/react-window-2.3.4.tgz", - "integrity": "sha512-CnRWoRg+ZnQkLcULSNdbgKJnfcexy9x+9ELOATmDlDv3ZoADyLJc22vN3JRvMV651A6gFwYBlxllU9X+H9dyhQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/react-window/-/react-window-2.5.0.tgz", + "integrity": "sha512-2oQiMo+lT5omOYaBJnloTK19yZDXqboDPMJP6li0gER0henua4iEz6BxzENJ1H5pNb6Kb2H4Lu0+YTuvqnw7QA==", "license": "MIT", "peerDependencies": { "react": "^18.0.0 || ^19.0.0", @@ -8080,13 +8016,13 @@ } }, "node_modules/rolldown": { - "version": "1.2.14", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.14.tgz", - "integrity": "sha512-eTBTTqMR6uHKLgcUqpJP8ntzDI6V4LYA8negAMBEI7gkgVvOdrx6VsvS2Ym+83KhOPdLCHWJu0w7UQFJZhHKNw==", + "version": "1.2.15", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.15.tgz", + "integrity": "sha512-6odND+fel5zVw3I4Yc2e69gvguDnX0CAAGiNDZSq4ik5WUcaLrkD2GLuog0XcODbor31hZ5ayEMgVDno+KPV5g==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.154.0", + "@oxc-project/types": "=0.155.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -8096,27 +8032,27 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm-eabi": "1.2.14", - "@rolldown/binding-android-arm64": "1.2.14", - "@rolldown/binding-darwin-arm64": "1.2.14", - "@rolldown/binding-darwin-x64": "1.2.14", - "@rolldown/binding-freebsd-x64": "1.2.14", - "@rolldown/binding-linux-arm-gnueabihf": "1.2.14", - "@rolldown/binding-linux-arm64-gnu": "1.2.14", - "@rolldown/binding-linux-arm64-musl": "1.2.14", - "@rolldown/binding-linux-ppc64-gnu": "1.2.14", - "@rolldown/binding-linux-s390x-gnu": "1.2.14", - "@rolldown/binding-linux-x64-gnu": "1.2.14", - "@rolldown/binding-linux-x64-musl": "1.2.14", - "@rolldown/binding-openharmony-arm64": "1.2.14", - "@rolldown/binding-win32-arm64-msvc": "1.2.14", - "@rolldown/binding-win32-x64-msvc": "1.2.14" + "@rolldown/binding-android-arm-eabi": "1.2.15", + "@rolldown/binding-android-arm64": "1.2.15", + "@rolldown/binding-darwin-arm64": "1.2.15", + "@rolldown/binding-darwin-x64": "1.2.15", + "@rolldown/binding-freebsd-x64": "1.2.15", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.15", + "@rolldown/binding-linux-arm64-gnu": "1.2.15", + "@rolldown/binding-linux-arm64-musl": "1.2.15", + "@rolldown/binding-linux-ppc64-gnu": "1.2.15", + "@rolldown/binding-linux-s390x-gnu": "1.2.15", + "@rolldown/binding-linux-x64-gnu": "1.2.15", + "@rolldown/binding-linux-x64-musl": "1.2.15", + "@rolldown/binding-openharmony-arm64": "1.2.15", + "@rolldown/binding-win32-arm64-msvc": "1.2.15", + "@rolldown/binding-win32-x64-msvc": "1.2.15" } }, "node_modules/rollup": { - "version": "4.64.7", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.64.7.tgz", - "integrity": "sha512-aCiJONoZp0lNGJ6sYqspLkh6UXaWEey/7Ko2TZyXQ4kgzAhDUxAgbt/oulXKmD+zFHXw1k+RF6ZZWOrjp7DZnQ==", + "version": "4.65.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.65.0.tgz", + "integrity": "sha512-QVCvQUTGDN6JRwi3jVGCY3H4aTHvi9rX0LyoBMkGUvdh/Z6O51CzcLz85BWZaTCDGhl6ySGqYZs+xI1jmPqGcw==", "dev": true, "license": "MIT", "dependencies": { @@ -8131,31 +8067,31 @@ }, "optionalDependencies": { "@napi-rs/lzma-linux-x64-gnu": "1.5.1", - "@rollup/rollup-android-arm-eabi": "4.64.7", - "@rollup/rollup-android-arm64": "4.64.7", - "@rollup/rollup-darwin-arm64": "4.64.7", - "@rollup/rollup-darwin-x64": "4.64.7", - "@rollup/rollup-freebsd-arm64": "4.64.7", - "@rollup/rollup-freebsd-x64": "4.64.7", - "@rollup/rollup-linux-arm-gnueabihf": "4.64.7", - "@rollup/rollup-linux-arm-musleabihf": "4.64.7", - "@rollup/rollup-linux-arm64-gnu": "4.64.7", - "@rollup/rollup-linux-arm64-musl": "4.64.7", - "@rollup/rollup-linux-loong64-gnu": "4.64.7", - "@rollup/rollup-linux-loong64-musl": "4.64.7", - "@rollup/rollup-linux-ppc64-gnu": "4.64.7", - "@rollup/rollup-linux-ppc64-musl": "4.64.7", - "@rollup/rollup-linux-riscv64-gnu": "4.64.7", - "@rollup/rollup-linux-riscv64-musl": "4.64.7", - "@rollup/rollup-linux-s390x-gnu": "4.64.7", - "@rollup/rollup-linux-x64-gnu": "4.64.7", - "@rollup/rollup-linux-x64-musl": "4.64.7", - "@rollup/rollup-openbsd-x64": "4.64.7", - "@rollup/rollup-openharmony-arm64": "4.64.7", - "@rollup/rollup-win32-arm64-msvc": "4.64.7", - "@rollup/rollup-win32-ia32-msvc": "4.64.7", - "@rollup/rollup-win32-x64-gnu": "4.64.7", - "@rollup/rollup-win32-x64-msvc": "4.64.7", + "@rollup/rollup-android-arm-eabi": "4.65.0", + "@rollup/rollup-android-arm64": "4.65.0", + "@rollup/rollup-darwin-arm64": "4.65.0", + "@rollup/rollup-darwin-x64": "4.65.0", + "@rollup/rollup-freebsd-arm64": "4.65.0", + "@rollup/rollup-freebsd-x64": "4.65.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.65.0", + "@rollup/rollup-linux-arm-musleabihf": "4.65.0", + "@rollup/rollup-linux-arm64-gnu": "4.65.0", + "@rollup/rollup-linux-arm64-musl": "4.65.0", + "@rollup/rollup-linux-loong64-gnu": "4.65.0", + "@rollup/rollup-linux-loong64-musl": "4.65.0", + "@rollup/rollup-linux-ppc64-gnu": "4.65.0", + "@rollup/rollup-linux-ppc64-musl": "4.65.0", + "@rollup/rollup-linux-riscv64-gnu": "4.65.0", + "@rollup/rollup-linux-riscv64-musl": "4.65.0", + "@rollup/rollup-linux-s390x-gnu": "4.65.0", + "@rollup/rollup-linux-x64-gnu": "4.65.0", + "@rollup/rollup-linux-x64-musl": "4.65.0", + "@rollup/rollup-openbsd-x64": "4.65.0", + "@rollup/rollup-openharmony-arm64": "4.65.0", + "@rollup/rollup-win32-arm64-msvc": "4.65.0", + "@rollup/rollup-win32-ia32-msvc": "4.65.0", + "@rollup/rollup-win32-x64-gnu": "4.65.0", + "@rollup/rollup-win32-x64-msvc": "4.65.0", "fsevents": "~2.3.2" } }, @@ -8251,9 +8187,9 @@ } }, "node_modules/serialize-javascript": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.1.2.tgz", - "integrity": "sha512-GL2BWwVa6JydKO6l/ljVgjAZF4QJ3S7dWDWi53s5GZT8PJzD2fNxi67HANQGKAqPrwEpL5ba7gUBGi0Ls/sEoQ==", + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.1.4.tgz", + "integrity": "sha512-FqlEuoTq/zRmA4Lg6aOqyH3lCHbUtCB0bmHCeFniX2GBdDqMJM3FwdvEhlE5Pim1dlt2FfBdVPmUNNiGhhKqpw==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -8540,10 +8476,8 @@ } }, "node_modules/skelehash-wasm": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/skelehash-wasm/-/skelehash-wasm-0.1.0.tgz", - "integrity": "sha512-QdxF9YsJvKlT93O70dXFaWnsKVX7KDD0RgYf9cwgOT6kGnSMOdsO0rsdge+5Tg+vv6BjivbJ/2o5P1KcQsavEw==", - "license": "MIT" + "resolved": "../skelehash-wasm", + "link": true }, "node_modules/smob": { "version": "1.6.2", @@ -9162,16 +9096,16 @@ "license": "MIT" }, "node_modules/vite": { - "version": "8.3.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.4.tgz", - "integrity": "sha512-IftLE8phJhdNRIGNEV4JCCvfNScoZQVfcXaN8TQropWGJtOHcu+iAB9pHcuGvmEb/kddw0LBe/jS8ztdC6xdiQ==", + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.5.tgz", + "integrity": "sha512-z1YpjieJ9g0ebTmQpLBv/oq9E3F9EIlOe+7LahW8SrE3LTiG3udBRUXQOlYXP9b+IC2q2phHeVxj9xGlw34OEQ==", "dev": true, "license": "MIT", "dependencies": { "lightningcss": "^1.33.0", "picomatch": "^4.0.7", - "postcss": "^8.5.29", - "rolldown": "~1.2.12", + "postcss": "^8.5.30", + "rolldown": "~1.2.14", "tinyglobby": "^0.2.17" }, "bin": { @@ -9188,7 +9122,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.7.1", + "@vitejs/devtools": "^0.7.1 || ^0.8.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", @@ -9707,22 +9641,6 @@ "dev": true, "license": "ISC" }, - "node_modules/yaml": { - "version": "2.9.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.1.tgz", - "integrity": "sha512-3NxN8+78OdzbT7C/WjGsyfPAtJaN3FNDsWxv7Y7mcDsT/oOmgW8BpyQQFFBnvZE3j9Y2Sdz1ULFLezL7Eb2yFw==", - "extraneous": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", diff --git a/package.json b/package.json index ee33845..a28be52 100644 --- a/package.json +++ b/package.json @@ -33,8 +33,6 @@ "@mui/material": "^9.5.0", "@shopify/draggable": "^1.2.1", "@uiw/react-codemirror": "^4.25.12", - "ag-grid-community": "^36.2.0", - "ag-grid-react": "^36.2.0", "dashgui": "file:../dashgui", "flexsearch": "^0.8.212", "jsbarcode": "^3.12.3", @@ -45,9 +43,8 @@ "react-canvas-label-editor": "github:sebseb7/react-canvas-label-editor", "react-dom": "^19.3.1", "react-router-dom": "^7.18.4", - "react-virtual-aggridautomat": "file:../react-virtual-aggridautomat", "react-window": "^2.3.4", - "skelehash-wasm": "^0.1.0", + "skelehash-wasm": "file:../skelehash-wasm", "sortablejs": "^1.15.7", "thumbhash": "^0.1.1" }, diff --git a/src/api/article.js b/src/api/article.js index 0ff82c0..b185b24 100644 --- a/src/api/article.js +++ b/src/api/article.js @@ -50,11 +50,19 @@ export const article = { // #endregion /** - * GET /api/article/:sku/history + * GET /api/article/:sku/history?offset=0&limit=50&search=...&seekMonths=-1 + * @param {string} sku + * @param {{ offset?: number, limit?: number, search?: string, seekMonths?: number }} [params] + * → { history: ArticleHistoryEntry[], total: number, unfilteredTotal?: number, offset: number, limit: number } */ - getBySkuHistory(sku, { limit } = {}) { + getBySkuHistory(sku, { offset = 0, limit = 50, search, seekMonths } = {}) { const params = new URLSearchParams(); - if (limit != null) params.set('limit', String(limit)); + if (offset != null) params.set('offset', String(Math.max(0, Math.floor(Number(offset) || 0)))); + if (limit != null) params.set('limit', String(Math.max(1, Math.floor(Number(limit) || 50)))); + if (search && String(search).trim()) params.set('search', String(search).trim()); + if (seekMonths != null && Number(seekMonths) < 0) { + params.set('seekMonths', String(Math.floor(Number(seekMonths)))); + } const qs = params.toString(); return http(`/api/article/${encodeURIComponent(sku)}/history${qs ? `?${qs}` : ''}`); }, diff --git a/src/automats/articleDetailAutomat.js b/src/automats/articleDetailAutomat.js index 514cecd..af6d71d 100644 --- a/src/automats/articleDetailAutomat.js +++ b/src/automats/articleDetailAutomat.js @@ -34,26 +34,72 @@ import { requireArray, requireObject } from '../utils/apiShape'; * @property {number|null} taxRate Tax rate in percent. */ +import { createChunkListAutomat } from './createChunkListAutomat'; +import authAutomat from './authAutomat'; + /** - * Per-SKU article change history (`GET /api/article/{sku}/history`). - * - * The backend returns the full list; pagination happens client-side in - * `ArticleHistoryTab`. Keyed by SKU so several tabs can watch the same article. - * - * @type {KeyedAutomat>} + * Registry of SKU-specific chunk-list automats for article history. + * @type {Map} */ -export const articleHistoryAutomat = new KeyedAutomat( - null, - {}, - { - name: 'articleHistory', - loader: async (sku) => { - const res = await articleApi.getBySkuHistory(String(sku)); - requireObject(res, 'GET /api/article/:sku/history'); - return requireArray(res.history, 'history'); - }, +const skuHistoryAutomats = new Map(); + +/** + * Gets or creates the chunk-list automat for a specific article's history. + * + * @param {string|number} sku Article SKU. + * @returns {import('react-automat').Automat} Configured chunk-list automat for the SKU. + */ +export function getArticleHistoryAutomat(sku) { + const key = String(sku); + let inst = skuHistoryAutomats.get(key); + if (!inst) { + inst = createChunkListAutomat({ + name: `articleHistory:${key}`, + chunkSize: 50, + maxLruChunks: 50, + fetchPage: (params) => articleApi.getBySkuHistory(key, params), + }); + skuHistoryAutomats.set(key, inst); + } + return inst; +} + +/** + * Per-SKU article change history manager (`GET /api/article/{sku}/history`). + * + * Backed by chunk-list automats (`createChunkListAutomat`) keyed by SKU with + * multi-filter memory caching, LRU eviction, and infinite-scrolling / FillSpace support. + */ +export const articleHistoryAutomat = { + get: getArticleHistoryAutomat, + key: getArticleHistoryAutomat, + has(sku) { + return skuHistoryAutomats.has(String(sku)); }, -); + async load(sku) { + const inst = getArticleHistoryAutomat(sku); + return inst.getItems(); + }, + async reload(sku) { + const inst = skuHistoryAutomats.get(String(sku)); + if (inst) { + await inst.actions.reload(); + } + }, + reset() { + for (const inst of skuHistoryAutomats.values()) { + inst.actions.reset(); + } + skuHistoryAutomats.clear(); + }, +}; + +// Reset on logout or company change +authAutomat.subscribe((auth) => { + if (auth.status === 'anon') { + articleHistoryAutomat.reset(); + } +}); /** * Suppliers assigned to an article (`GET /api/article/{sku}/supplier`). diff --git a/src/automats/index.js b/src/automats/index.js index d4a5077..f9ccf1e 100644 --- a/src/automats/index.js +++ b/src/automats/index.js @@ -117,7 +117,7 @@ export { createListAutomat, selectListItems, selectListStatus } from './createLi /** Per-SKU article detail views keyed by SKU. */ -export { articleHistoryAutomat, articleSupplierAutomat } from './articleDetailAutomat'; +export { articleHistoryAutomat, getArticleHistoryAutomat, articleSupplierAutomat } from './articleDetailAutomat'; /** Single shared GET /api/events connection. */ export { default as sseAutomat, invalidateArticle } from './sseAutomat'; diff --git a/src/components/article/tabs/ArticleHistoryTab.jsx b/src/components/article/tabs/ArticleHistoryTab.jsx index c56f38c..278f0c8 100644 --- a/src/components/article/tabs/ArticleHistoryTab.jsx +++ b/src/components/article/tabs/ArticleHistoryTab.jsx @@ -1,27 +1,48 @@ -import { PureComponent } from 'react'; -import Table from '@mui/material/Table'; -import TableBody from '@mui/material/TableBody'; -import TableCell from '@mui/material/TableCell'; -import TableHead from '@mui/material/TableHead'; -import TableRow from '@mui/material/TableRow'; +import { PureComponent, createRef } from 'react'; +import Box from '@mui/material/Box'; +import Button from '@mui/material/Button'; +import Chip from '@mui/material/Chip'; +import CircularProgress from '@mui/material/CircularProgress'; import Link from '@mui/material/Link'; +import ListItemButton from '@mui/material/ListItemButton'; +import Skeleton from '@mui/material/Skeleton'; +import Tooltip from '@mui/material/Tooltip'; +import Typography from '@mui/material/Typography'; +import ViewModuleIcon from '@mui/icons-material/ViewModule'; import { enqueueSnackbar } from 'notistack'; -import { articleHistoryAutomat } from '../../../automats/articleDetailAutomat'; +import SingleLineTextEdit from 'dashgui/SingleLineTextEdit'; +import FillSpace from 'dashgui/FillSpace'; +import BackendError from '../../BackendError'; +import { getArticleHistoryAutomat } from '../../../automats/articleDetailAutomat'; import sseAutomat from '../../../automats/sseAutomat'; import shipmentAutomat from '../../../automats/shipmentAutomat'; -import { shipment as shipmentApi } from '../../../api'; +import orderAutomat from '../../../automats/orderAutomat'; +import entityAutomat from '../../../automats/entityAutomat'; +import brandAutomat from '../../../automats/brandAutomat'; +import { shipment as shipmentApi, order as orderApi } from '../../../api'; import { ShipmentDetailDialog } from '../../manifest'; +import SkeleHashImage from '../../settings/SkeleHashImage'; import withNavigate from '../../withNavigate'; +import { backendErrorFrom } from '../../../utils/backendError'; import { notifyError } from '../../../utils/notify'; -import ResultsPagination from '../ResultsPagination'; -import { - SCRIM_SOFT, -} from '../../../colors'; +import { DEFAULT_CHUNK_SIZE as CHUNK_SIZE } from '../../../automats/createChunkListAutomat'; -const PAGE_SIZE = 20; - -function formatDate(iso) { - return new Date(iso).toLocaleString('de-DE'); +function formatDateTime(val) { + if (!val) return '–'; + try { + const d = new Date(val); + if (isNaN(d.getTime())) return String(val); + return d.toLocaleString('de-DE', { + day: '2-digit', + month: '2-digit', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + }); + } catch { + return String(val); + } } function decodeMeta(meta) { @@ -34,140 +55,84 @@ function decodeMeta(meta) { } } -const HISTORY_DATE_CELL_BORDER = `1px solid ${SCRIM_SOFT}`; - -const dateDividerSx = { - borderBottom: HISTORY_DATE_CELL_BORDER, -}; - -const dateCellSx = { - borderBottom: HISTORY_DATE_CELL_BORDER, - verticalAlign: 'middle', -}; - -class ArticleHistoryTab extends PureComponent { - constructor(props) { - super(props); - this.state = { - all: [], - skip: 0, - selectedShipment: null, - loadingShipment: false, - }; - this.handlePageChange = this.handlePageChange.bind(this); - this.handleCloseShipment = this.handleCloseShipment.bind(this); - } - - componentDidMount() { - this.watch(); - void articleHistoryAutomat.load(String(this.props.sku)).catch((err) => { - if (this.unsub) notifyError(err); - }); - } - - componentDidUpdate(prevProps) { - if (prevProps.sku !== this.props.sku) { - this.watch(); - void articleHistoryAutomat.load(String(this.props.sku)).catch((err) => { - if (this.unsub) notifyError(err); - }); - } - } - - componentWillUnmount() { - this.unsub?.(); - this.unsub = null; - this.unwatchSignal?.(); - this.unwatchSignal = null; - } - - /** - * Subscribes to the keyed history cache and to the article SSE signal. - * The backend re-emits `article-` whenever the article changes, and - * `sseAutomat` reloads the history key for us. - */ - watch() { - this.unsub?.(); - const handle = articleHistoryAutomat.key(String(this.props.sku)); - this.unsub = handle.subscribe(this, (item) => { - const all = Array.isArray(item.data) ? item.data : []; - this.setState({ all }); - }); - - this.unwatchSignal?.(); - this.unwatchSignal = sseAutomat.actions.watchArticle(String(this.props.sku), () => { - void articleHistoryAutomat.reload(String(this.props.sku)).catch(() => {}); - }); - } - - /** Client-side pagination over the full history list. */ - pageOf(all, skip) { - return all.slice(skip, skip + PAGE_SIZE); - } - - handlePageChange(_event, page) { - this.setState({ skip: (page - 1) * PAGE_SIZE }); - } - - handleCloseShipment() { - this.setState({ selectedShipment: null }); - } - - handleOpenShipment = async (shipmentNumber, shipmentId = null) => { - if (shipmentId) { - this.setState({ selectedShipment: { id: shipmentId, number: shipmentNumber } }); - return; - } - if (!shipmentNumber) return; - - this.setState({ loadingShipment: true }); - try { - const cached = shipmentAutomat.state.items?.find( - (s) => s && String(s.number).toLowerCase() === String(shipmentNumber).toLowerCase() - ); - if (cached?.id) { - this.setState({ selectedShipment: cached, loadingShipment: false }); - return; - } - - const res = await shipmentApi.list({ search: shipmentNumber }); - const shipments = Array.isArray(res?.shipments) ? res.shipments : []; - const match = shipments.find( - (s) => String(s.number).toLowerCase() === String(shipmentNumber).toLowerCase() - ) || shipments[0]; - - if (match?.id) { - this.setState({ selectedShipment: match, loadingShipment: false }); - } else { - enqueueSnackbar(`Lieferschein „${shipmentNumber}“ nicht gefunden.`, { variant: 'warning' }); - this.setState({ loadingShipment: false }); - } - } catch (err) { - this.setState({ loadingShipment: false }); - notifyError(err); - } +// Dummy history entry for layout and FillSpace row measurement +export function createDummyTestArticleHistory() { + return { + id: 999999, + date: '2030-10-30T12:00:00Z', + text: 'Preis geändert von 10,00 € auf 12,50 € durch Benutzer Max Mustermann für Lieferschein LS-123456', }; +} - renderEntryText(entry) { - const meta = decodeMeta(entry.meta); - const shipmentNumber = meta?.shipmentNumber || (meta?.type === 'shipment' ? meta?.manifestNumber : null); - const regexMatch = !shipmentNumber && entry.text ? entry.text.match(/Lieferschein\s+([A-Za-z0-9\-_]+)/) : null; - const effectiveShipmentNumber = shipmentNumber || regexMatch?.[1] || null; +const rowGridSx = { + display: 'grid', + gridTemplateColumns: 'minmax(150px, max-content) minmax(260px, 1fr)', + gridTemplateRows: '0px 1fr', + rowGap: 0, + columnGap: 1.5, + alignItems: 'center', + width: '100%', + boxSizing: 'border-box', +}; - if (!effectiveShipmentNumber || !entry.text) { - return entry.text; - } +const ellipsisSx = { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }; - const shipmentId = meta?.shipmentId ?? meta?.manifestId ?? meta?.id ?? null; - const targetPattern = `Lieferschein ${effectiveShipmentNumber}`; - const idx = entry.text.indexOf(targetPattern); +const measuringCellSx = { + visibility: 'hidden', + height: 0, + boxSizing: 'border-box', + pointerEvents: 'none', + textTransform: 'none', + letterSpacing: 'normal', +}; - const linkElement = (label) => ( +const headerCellSx = { + color: 'text.secondary', + typography: 'caption', + fontSize: '0.75rem', + fontWeight: 600, + textTransform: 'uppercase', + letterSpacing: '0.04em', + userSelect: 'none', +}; + +function renderInvisibleDummyRow(dummy) { + const d = dummy || createDummyTestArticleHistory(); + return ( + <> + + {formatDateTime(d.date)} + + + {d.text} + + + ); +} + +/** + * Ambient row context for `ArticleHistoryRow` callbacks, mirroring the pattern in `QuoteList`. + */ +const rowContext = { + headerItem: null, + onOpenShipment: null, + onOpenOrder: null, + onOpenCustomer: null, + onOpenBrand: null, +}; + +// MARK: +class ArticleHistoryRow extends PureComponent { + renderLink(label, onClick) { + return ( this.handleOpenShipment(effectiveShipmentNumber, shipmentId)} + onClick={(e) => { + e.stopPropagation(); + onClick?.(e); + }} sx={{ fontWeight: 600, verticalAlign: 'baseline', @@ -190,100 +155,771 @@ class ArticleHistoryTab extends PureComponent { {label} ); + } - if (idx !== -1) { - const before = entry.text.slice(0, idx); - const after = entry.text.slice(idx + targetPattern.length); - return ( - <> - {before} - {linkElement(targetPattern)} - {after} - - ); + collectSpans(text, meta) { + const spans = []; + if (!text) return spans; + const { onOpenShipment, onOpenOrder, onOpenCustomer, onOpenBrand } = rowContext; + + // 1. Lieferschein + const shipmentNumber = + meta?.shipmentNumber || (meta?.type === 'shipment' ? meta?.manifestNumber : null); + const regexShipment = + !shipmentNumber && text ? text.match(/Lieferschein\s+([A-Za-z0-9\-_]+)/) : null; + const effectiveShipmentNumber = shipmentNumber || regexShipment?.[1] || null; + + if (effectiveShipmentNumber) { + const shipmentId = meta?.shipmentId ?? meta?.manifestId ?? meta?.id ?? null; + const targetPattern = `Lieferschein ${effectiveShipmentNumber}`; + let idx = text.indexOf(targetPattern); + if (idx !== -1) { + spans.push({ + start: idx, + end: idx + targetPattern.length, + node: this.renderLink(targetPattern, () => + onOpenShipment?.(effectiveShipmentNumber, shipmentId), + ), + }); + } else { + idx = text.indexOf(effectiveShipmentNumber); + if (idx !== -1) { + spans.push({ + start: idx, + end: idx + effectiveShipmentNumber.length, + node: this.renderLink(effectiveShipmentNumber, () => + onOpenShipment?.(effectiveShipmentNumber, shipmentId), + ), + }); + } + } } - const numIdx = entry.text.indexOf(effectiveShipmentNumber); - if (numIdx !== -1) { - const before = entry.text.slice(0, numIdx); - const after = entry.text.slice(numIdx + effectiveShipmentNumber.length); - return ( - <> - {before} - {linkElement(effectiveShipmentNumber)} - {after} - - ); + // 2. Auftrag (Order) + const orderNumber = + meta?.orderNumber || (meta?.type === 'order' ? meta?.number : null); + const regexOrder = + !orderNumber && text ? text.match(/Auftrag\s+([A-Za-z0-9\-_]+)/) : null; + const effectiveOrderNumber = orderNumber || regexOrder?.[1] || null; + + if (effectiveOrderNumber) { + const orderId = meta?.orderId ?? null; + const targetPattern = `Auftrag ${effectiveOrderNumber}`; + let idx = text.indexOf(targetPattern); + if (idx !== -1) { + spans.push({ + start: idx, + end: idx + targetPattern.length, + node: this.renderLink(targetPattern, () => + onOpenOrder?.(orderId, effectiveOrderNumber), + ), + }); + } else { + idx = text.indexOf(effectiveOrderNumber); + if (idx !== -1) { + spans.push({ + start: idx, + end: idx + effectiveOrderNumber.length, + node: this.renderLink(effectiveOrderNumber, () => + onOpenOrder?.(orderId, effectiveOrderNumber), + ), + }); + } + } } + // 3. Kunde (Customer) + const customerName = + meta?.customerName || (text.match(/Kunde:\s*"([^"]+)"/)?.[1] ?? null); + + if (customerName) { + const inQuotes = `"${customerName}"`; + let idx = text.indexOf(inQuotes); + if (idx !== -1) { + spans.push({ + start: idx, + end: idx + inQuotes.length, + node: this.renderLink(inQuotes, () => onOpenCustomer?.(customerName)), + }); + } else { + idx = text.indexOf(customerName); + if (idx !== -1) { + spans.push({ + start: idx, + end: idx + customerName.length, + node: this.renderLink(customerName, () => onOpenCustomer?.(customerName)), + }); + } + } + } + + // 4. Marke (Brand) + const brandNames = [meta?.newBrandName, meta?.oldBrandName].filter(Boolean); + for (const bName of brandNames) { + const inQuotes = `"${bName}"`; + let idx = text.indexOf(inQuotes); + if (idx !== -1) { + spans.push({ + start: idx, + end: idx + inQuotes.length, + node: this.renderLink(inQuotes, () => onOpenBrand?.(bName)), + }); + } else { + idx = text.indexOf(bName); + if (idx !== -1) { + spans.push({ + start: idx, + end: idx + bName.length, + node: this.renderLink(bName, () => onOpenBrand?.(bName)), + }); + } + } + } + + return spans; + } + + renderEntrySpans(text, meta) { + if (!text) return null; + const allSpans = this.collectSpans(text, meta); + if (allSpans.length === 0) return text; + + allSpans.sort((a, b) => a.start - b.start || (b.end - b.start) - (a.end - a.start)); + + const nonOverlapping = []; + let lastEnd = 0; + for (const span of allSpans) { + if (span.start >= lastEnd) { + nonOverlapping.push(span); + lastEnd = span.end; + } + } + + const fragments = []; + let cur = 0; + for (let i = 0; i < nonOverlapping.length; i++) { + const span = nonOverlapping[i]; + if (span.start > cur) { + fragments.push(text.slice(cur, span.start)); + } + fragments.push({span.node}); + cur = span.end; + } + if (cur < text.length) { + fragments.push(text.slice(cur)); + } + return fragments; + } + + renderSkelehashThumb(meta) { + if (!meta?.skelehash) return null; + return ( - <> - {linkElement(`Lieferschein ${effectiveShipmentNumber}`)} {entry.text} - + + + ); } render() { - const { all, skip, selectedShipment } = this.state; - const total = all.length; - const history = this.pageOf(all, skip); + const { item, disabled, headerItem } = this.props; + const dummy = headerItem || rowContext.headerItem; - const pageCount = Math.max(1, Math.ceil(total / PAGE_SIZE)); - const currentPage = Math.floor(skip / PAGE_SIZE) + 1; - const showPagination = total > PAGE_SIZE; + if (!item) { + if (disabled) { + return ( + +   + + ); + } + return ( + + {renderInvisibleDummyRow(dummy)} + + + + + + + + ); + } + + const meta = decodeMeta(item.meta); return ( - <> - + {renderInvisibleDummyRow(dummy)} + + + + {formatDateTime(item.date || item.createdAt)} + + + + - - - + + {this.renderEntrySpans(item.text, meta)} + + + + + ); + } +} + +// MARK: +class ArticleHistorySearchField extends PureComponent { + constructor(props) { + super(props); + const { automat } = props; + const s = automat.state; + const stats = automat.getChunkStats?.(); + this.state = { + input: s.filter ?? '', + seekMonths: s.seekMonths ?? 0, + seekYears: s.seekYears ?? 0, + negativeSeekMonths: s.negativeSeekMonths ?? 0, + lruChunksCount: stats?.lruChunksCount || 0, + maxLruChunks: stats?.maxLruChunks || 50, + filterCachesCount: stats?.filterCaches?.length || 1, + }; + } + + componentDidMount() { + this.subscribeAutomat(this.props.automat); + } + + componentDidUpdate(prevProps) { + if (prevProps.automat !== this.props.automat) { + this.unsubscribeAutomat(); + const { automat } = this.props; + const s = automat.state; + const stats = automat.getChunkStats?.(); + this.setState({ + input: s.filter ?? '', + seekMonths: s.seekMonths ?? 0, + seekYears: s.seekYears ?? 0, + negativeSeekMonths: s.negativeSeekMonths ?? 0, + lruChunksCount: stats?.lruChunksCount || 0, + maxLruChunks: stats?.maxLruChunks || 50, + filterCachesCount: stats?.filterCaches?.length || 1, + }); + this.subscribeAutomat(automat); + } + } + + componentWillUnmount() { + this.unsubscribeAutomat(); + } + + subscribeAutomat(automat) { + this.unsub = automat.subscribe(this, (state) => ({ + input: state.filter ?? '', + seekMonths: state.seekMonths ?? 0, + seekYears: state.seekYears ?? 0, + negativeSeekMonths: state.negativeSeekMonths ?? 0, + })); + if (import.meta.env.DEV) { + this.unsubStats = automat.subscribeChunkStats?.((stats) => { + this.setState({ + lruChunksCount: stats.lruChunksCount, + maxLruChunks: stats.maxLruChunks, + filterCachesCount: stats.filterCaches?.length || 1, + }); + }); + } + } + + unsubscribeAutomat() { + this.unsub?.(); + this.unsub = null; + this.unsubStats?.(); + this.unsubStats = null; + } + + render() { + const { inputRef, automat } = this.props; + const { input, seekMonths, seekYears } = this.state; + const monthActive = seekMonths > 0; + const monthLabel = !monthActive ? '-1 Month' : `-${seekMonths} Month${seekMonths > 1 ? 's' : ''}`; + const yearActive = seekYears > 0; + const yearLabel = !yearActive ? '-1 Year' : `-${seekYears} Year${seekYears > 1 ? 's' : ''}`; + + return ( + + {/* Top row: search field */} + + automat.actions.filter(next)} + /> + + + {/* Filter Bar: Negativeseek (-1 Month, -1 Year, Reset) & Chunk-Cache Monitor */} + + + + + + + + + + {import.meta.env.DEV && ( + + } + label={ + this.state.lruChunksCount > 0 + ? `Chunk-Cache (${this.state.lruChunksCount}/${this.state.maxLruChunks || 50})` + : 'Chunk-Cache' + } + onClick={() => + window.dispatchEvent( + new CustomEvent('dash:toggle-chunk-monitor', { + detail: { target: automat.name }, + }), + ) + } sx={{ - ...dateDividerSx, - width: '1%', - whiteSpace: 'nowrap', - verticalAlign: 'middle', + cursor: 'pointer', + height: 28, + fontWeight: 600, + fontSize: '0.75rem', + bgcolor: 'background.paper', + boxShadow: 1, + '&:hover': { bgcolor: 'action.hover' }, + }} + /> + + )} + + + ); + } +} + +// MARK: +class ArticleHistoryTab extends PureComponent { + constructor(props) { + super(props); + this.headerItem = createDummyTestArticleHistory(); + this.automat = getArticleHistoryAutomat(props.sku); + this.state = { + items: this.automat.getItems(), + unfilteredTotal: this.automat.state.unfilteredTotal ?? 0, + filterKey: this.automat.getFilterKey?.() ?? '', + status: this.automat.state.status, + error: this.automat.state.error, + selectedShipment: null, + loadingShipment: false, + }; + this.searchRef = createRef(); + this.handlePageChange = this.handlePageChange.bind(this); + this.handleRetry = this.handleRetry.bind(this); + this.handleCloseShipment = this.handleCloseShipment.bind(this); + this.handleOpenShipment = this.handleOpenShipment.bind(this); + this.handleOpenOrder = this.handleOpenOrder.bind(this); + this.handleOpenCustomer = this.handleOpenCustomer.bind(this); + this.handleOpenBrand = this.handleOpenBrand.bind(this); + } + + componentDidMount() { + this.watch(this.props.sku); + + if (entityAutomat.state.status === 'idle') { + void entityAutomat.actions.load().catch(() => {}); + } + if (brandAutomat.state.status === 'idle') { + void brandAutomat.actions.load().catch(() => {}); + } + } + + componentDidUpdate(prevProps) { + if (prevProps.sku !== this.props.sku) { + this.watch(this.props.sku); + } + } + + componentWillUnmount() { + this.unsub?.(); + this.unsub = null; + this.unwatchSignal?.(); + this.unwatchSignal = null; + } + + watch(sku) { + this.unsub?.(); + this.unwatchSignal?.(); + + this.automat = getArticleHistoryAutomat(sku); + this.setState({ + items: this.automat.getItems(), + unfilteredTotal: this.automat.state.unfilteredTotal ?? 0, + filterKey: this.automat.getFilterKey?.() ?? '', + status: this.automat.state.status, + error: this.automat.state.error, + }); + + this.unsub = this.automat.subscribe(this, (state) => ({ + items: state.items, + unfilteredTotal: state.unfilteredTotal ?? 0, + filterKey: this.automat.getFilterKey(state), + status: state.status, + error: state.error, + })); + + this.unwatchSignal = sseAutomat.actions.watchArticle(String(sku), () => { + void this.automat.actions.reload().catch(() => {}); + }); + } + + handlePageChange(page, meta) { + const pageSize = meta?.pageSize ?? 10; + const startIndex = (page - 1) * pageSize; + const items = this.state.items; + const maxIndex = items ? items.length - 1 : startIndex; + const endIndex = Math.min(maxIndex, startIndex + pageSize - 1); + + const startChunk = Math.floor(startIndex / CHUNK_SIZE); + const endChunk = Math.floor(endIndex / CHUNK_SIZE); + + this.automat.requireChunk(startChunk, endChunk); + } + + handleRetry() { + void this.automat.actions.requireChunk(0, 0, { immediate: true }).catch(() => {}); + } + + handleCloseShipment() { + this.setState({ selectedShipment: null }); + } + + async handleOpenShipment(shipmentNumber, shipmentId = null) { + if (shipmentId) { + this.setState({ selectedShipment: { id: shipmentId, number: shipmentNumber } }); + return; + } + if (!shipmentNumber) return; + + this.setState({ loadingShipment: true }); + try { + const cached = shipmentAutomat.state.items?.find( + (s) => s && String(s.number).toLowerCase() === String(shipmentNumber).toLowerCase(), + ); + if (cached?.id) { + this.setState({ selectedShipment: cached, loadingShipment: false }); + return; + } + + const res = await shipmentApi.list({ search: shipmentNumber }); + const shipments = Array.isArray(res?.shipments) ? res.shipments : []; + const match = shipments.find( + (s) => String(s.number).toLowerCase() === String(shipmentNumber).toLowerCase(), + ) || shipments[0]; + + if (match?.id) { + this.setState({ selectedShipment: match, loadingShipment: false }); + } else { + enqueueSnackbar(`Lieferschein „${shipmentNumber}“ nicht gefunden.`, { variant: 'warning' }); + this.setState({ loadingShipment: false }); + } + } catch (err) { + this.setState({ loadingShipment: false }); + notifyError(err); + } + } + + async handleOpenOrder(orderId, orderNumber) { + if (orderId) { + this.props.navigate(`/auftrag/bestellung/${orderId}`); + return; + } + if (!orderNumber) return; + + const cached = orderAutomat.state.items?.find( + (o) => o && String(o.number).toLowerCase() === String(orderNumber).toLowerCase(), + ); + if (cached?.id) { + this.props.navigate(`/auftrag/bestellung/${cached.id}`); + return; + } + + try { + const res = await orderApi.list({ search: orderNumber }); + const orders = Array.isArray(res?.orders) ? res.orders : []; + const match = orders.find( + (o) => String(o.number).toLowerCase() === String(orderNumber).toLowerCase(), + ) || orders[0]; + + if (match?.id) { + this.props.navigate(`/auftrag/bestellung/${match.id}`); + } else { + this.props.navigate(`/auftrag/bestellung?search=${encodeURIComponent(orderNumber)}`); + } + } catch { + this.props.navigate(`/auftrag/bestellung?search=${encodeURIComponent(orderNumber)}`); + } + } + + async handleOpenCustomer(customerName) { + if (!customerName) return; + const target = String(customerName).trim().toLowerCase(); + + const findInItems = (items) => (items || []).find((c) => { + const full = [c.firstName, c.name].filter(Boolean).join(' ').trim().toLowerCase(); + const nameOnly = String(c.name || '').trim().toLowerCase(); + return full === target || nameOnly === target; + }); + + let match = findInItems(entityAutomat.state.items); + if (!match && entityAutomat.state.status !== 'loading') { + try { + const loaded = await entityAutomat.actions.load(); + match = findInItems(loaded || entityAutomat.state.items); + } catch {} + } + + if (match?.id) { + this.props.navigate(`/kunde/${match.id}`); + } else { + this.props.navigate(`/kunde?search=${encodeURIComponent(customerName)}`); + } + } + + handleOpenBrand(brandName) { + if (!brandName) return; + brandAutomat.actions.filter(brandName); + this.props.navigate('/artikel/marken'); + } + + render() { + const { items, unfilteredTotal, filterKey, status, error, selectedShipment } = this.state; + const isFailed = items === null && status === 'failed'; + + rowContext.onOpenShipment = this.handleOpenShipment; + rowContext.onOpenOrder = this.handleOpenOrder; + rowContext.onOpenCustomer = this.handleOpenCustomer; + rowContext.onOpenBrand = this.handleOpenBrand; + rowContext.headerItem = this.headerItem; + + return ( + + + + {isFailed ? ( + + + + ) : ( + + + {renderInvisibleDummyRow(this.headerItem)} + Datum + Änderung / Ereignis + + } + onPageChange={this.handlePageChange} + /> + {items === null && ( + - Datum - - - {showPagination ? ( - - ) : null} - - - - - {history.map((entry) => ( - - - {formatDate(entry.date)} - - - {this.renderEntryText(entry)} - - - ))} - -
+ + + )} + + )} {selectedShipment && ( )} - + ); } } diff --git a/src/index.css b/src/index.css index 9c2bb14..b3711d1 100644 --- a/src/index.css +++ b/src/index.css @@ -1,6 +1,3 @@ -@import 'ag-grid-community/styles/ag-grid.css'; -@import 'ag-grid-community/styles/ag-theme-alpine.css'; - /* App background. Provided as a CSS custom property by src/colors.js (installCssVars), with a hard-coded fallback for the very first paint. */ html,