diff --git a/README.md b/README.md index 7972bad7..5fb8fb12 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,6 @@ This readme file is used mostly to document project dependencies and conventions - js-file-download - use-debounce - qrcode.react - - html-to-image - zustand - zod - @hookform/resolvers diff --git a/TODO.txt b/TODO.txt index ab3e1681..7447f73a 100644 --- a/TODO.txt +++ b/TODO.txt @@ -8,9 +8,10 @@ For more specific TODOs see comments in code - Landing page - Design first user experience - Demo sandbox for anonymous users +- Save react-flow to vector image User profile: -- Settings + settings server persistency +- Settings server persistency - Profile pictures - Custom LibraryItem lists - Custom user filters and sharing filters @@ -39,7 +40,6 @@ User profile: [Tech] - duplicate syntax parsing and type info calculations to client. Consider moving backend to Nodejs or embedding c++ lib -- Testing E2E playwright [Deployment] @@ -60,7 +60,6 @@ Research and consider integration - skeleton loading https://react.dev/reference/react/Suspense -- backend error message unification - drf-messages https://drf-standardized-errors.readthedocs.io/en/latest/error_response.html diff --git a/rsconcept/frontend/package-lock.json b/rsconcept/frontend/package-lock.json index ecaa47a2..8bc71e61 100644 --- a/rsconcept/frontend/package-lock.json +++ b/rsconcept/frontend/package-lock.json @@ -19,7 +19,6 @@ "axios": "^1.7.9", "clsx": "^2.1.1", "global": "^4.4.0", - "html-to-image": "^1.11.13", "js-file-download": "^0.4.12", "qrcode.react": "^4.2.0", "react": "^19.0.0", @@ -6719,12 +6718,6 @@ "dev": true, "license": "MIT" }, - "node_modules/html-to-image": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz", - "integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==", - "license": "MIT" - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", diff --git a/rsconcept/frontend/package.json b/rsconcept/frontend/package.json index 509f03c9..e18f2788 100644 --- a/rsconcept/frontend/package.json +++ b/rsconcept/frontend/package.json @@ -24,7 +24,6 @@ "axios": "^1.7.9", "clsx": "^2.1.1", "global": "^4.4.0", - "html-to-image": "^1.11.13", "js-file-download": "^0.4.12", "qrcode.react": "^4.2.0", "react": "^19.0.0", diff --git a/rsconcept/frontend/src/features/help/items/ui/HelpOssGraph.tsx b/rsconcept/frontend/src/features/help/items/ui/HelpOssGraph.tsx index 64be15ef..84105109 100644 --- a/rsconcept/frontend/src/features/help/items/ui/HelpOssGraph.tsx +++ b/rsconcept/frontend/src/features/help/items/ui/HelpOssGraph.tsx @@ -10,7 +10,6 @@ import { IconExecute, IconFitImage, IconGrid, - IconImage, IconLineStraight, IconLineWave, IconNewItem, @@ -82,9 +81,6 @@ export function HelpOssGraph() {
  • Сохранить положения
  • -
  • - Сохранить в SVG -
  • diff --git a/rsconcept/frontend/src/features/help/items/ui/HelpRSGraphTerm.tsx b/rsconcept/frontend/src/features/help/items/ui/HelpRSGraphTerm.tsx index 85b9f8a6..99d920a6 100644 --- a/rsconcept/frontend/src/features/help/items/ui/HelpRSGraphTerm.tsx +++ b/rsconcept/frontend/src/features/help/items/ui/HelpRSGraphTerm.tsx @@ -11,7 +11,6 @@ import { IconGraphInputs, IconGraphMaximize, IconGraphOutputs, - IconImage, IconNewItem, IconOSS, IconPredecessor, @@ -85,9 +84,6 @@ export function HelpRSGraphTerm() { Открыть{' '} -
  • - Сохранить в формат PNG -
  • diff --git a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/OssFlow.tsx b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/OssFlow.tsx index f748e9a6..03883bdf 100644 --- a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/OssFlow.tsx +++ b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/OssFlow.tsx @@ -4,8 +4,6 @@ import { useEffect, useState } from 'react'; import { toast } from 'react-toastify'; import { Background, - getNodesBounds, - getViewportForBounds, type Node, ReactFlow, useEdgesState, @@ -13,7 +11,6 @@ import { useOnSelectionChange, useReactFlow } from 'reactflow'; -import { toPng } from 'html-to-image'; import { urls, useConceptNavigation } from '@/app'; import { useLibrary } from '@/features/library'; @@ -21,7 +18,6 @@ import { useLibrary } from '@/features/library'; import { Overlay } from '@/components/Container'; import { useMainHeight } from '@/stores/appLayout'; import { useTooltipsStore } from '@/stores/tooltips'; -import { APP_COLORS } from '@/styling/colors'; import { PARAMETER } from '@/utils/constants'; import { errorMsg } from '@/utils/labels'; @@ -203,39 +199,6 @@ export function OssFlow() { promptRelocateConstituents(target, getPositions()); } - function handleSaveImage() { - const canvas: HTMLElement | null = document.querySelector('.react-flow__viewport'); - if (canvas === null) { - toast.error(errorMsg.imageFailed); - return; - } - - const imageWidth = PARAMETER.ossImageWidth; - const imageHeight = PARAMETER.ossImageHeight; - const nodesBounds = getNodesBounds(nodes); - const viewport = getViewportForBounds(nodesBounds, imageWidth, imageHeight, ZOOM_MIN, ZOOM_MAX); - toPng(canvas, { - backgroundColor: APP_COLORS.bgDefault, - width: imageWidth, - height: imageHeight, - style: { - width: String(imageWidth), - height: String(imageHeight), - transform: `translate(${viewport.x}px, ${viewport.y}px) scale(${viewport.zoom})` - } - }) - .then(dataURL => { - const a = document.createElement('a'); - a.setAttribute('download', `${schema.alias}.png`); - a.setAttribute('href', dataURL); - a.click(); - }) - .catch(error => { - console.error(error); - toast.error(errorMsg.imageFailed); - }); - } - function handleContextMenu(event: React.MouseEvent, node: OssNode) { event.preventDefault(); event.stopPropagation(); @@ -306,7 +269,6 @@ export function OssFlow() { onExecute={handleExecuteSelected} onResetPositions={() => setToggleReset(prev => !prev)} onSavePositions={handleSavePositions} - onSaveImage={handleSaveImage} /> {menuProps ? ( diff --git a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/ToolbarOssGraph.tsx b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/ToolbarOssGraph.tsx index e92e5d69..beee6f8c 100644 --- a/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/ToolbarOssGraph.tsx +++ b/rsconcept/frontend/src/features/oss/pages/OssPage/EditorOssGraph/ToolbarOssGraph.tsx @@ -13,7 +13,6 @@ import { IconExecute, IconFitImage, IconGrid, - IconImage, IconLineStraight, IconLineWave, IconNewItem, @@ -34,7 +33,6 @@ interface ToolbarOssGraphProps { onEdit: () => void; onExecute: () => void; onFitView: () => void; - onSaveImage: () => void; onSavePositions: () => void; onResetPositions: () => void; } @@ -45,7 +43,6 @@ export function ToolbarOssGraph({ onEdit, onExecute, onFitView, - onSaveImage, onSavePositions, onResetPositions }: ToolbarOssGraphProps) { @@ -127,11 +124,6 @@ export function ToolbarOssGraph({ } onClick={toggleEdgeAnimate} /> - } - title='Сохранить изображение' - onClick={onSaveImage} - /> state.darkMode); const { schema, // selected, @@ -49,7 +42,7 @@ export function ToolbarTermGraph() { const filter = useTermGraphStore(state => state.filter); const setFilter = useTermGraphStore(state => state.setFilter); - const { fitView, getNodes } = useReactFlow(); + const { fitView } = useReactFlow(); function handleShowTypeGraph() { const typeInfo = schema.items.map(item => ({ @@ -79,39 +72,6 @@ export function ToolbarTermGraph() { }); } - function handleSaveImage() { - const canvas: HTMLElement | null = document.querySelector('.react-flow__viewport'); - if (canvas === null) { - toast.error(errorMsg.imageFailed); - return; - } - - const imageWidth = PARAMETER.ossImageWidth; - const imageHeight = PARAMETER.ossImageHeight; - const nodesBounds = getNodesBounds(getNodes()); - const viewport = getViewportForBounds(nodesBounds, imageWidth, imageHeight, ZOOM_MIN, ZOOM_MAX); - toPng(canvas, { - backgroundColor: darkMode ? APP_COLORS.bgDefaultDark : APP_COLORS.bgDefaultLight, - width: imageWidth, - height: imageHeight, - style: { - width: String(imageWidth), - height: String(imageHeight), - transform: `translate(${viewport.x}px, ${viewport.y}px) scale(${viewport.zoom * 2})` - } - }) - .then(dataURL => { - const a = document.createElement('a'); - a.setAttribute('download', `${schema.alias}.png`); - a.setAttribute('href', dataURL); - a.click(); - }) - .catch(error => { - console.error(error); - toast.error(errorMsg.imageFailed); - }); - } - function handleFitView() { setTimeout(() => { fitView({ duration: PARAMETER.zoomDuration, padding: VIEW_PADDING }); @@ -186,11 +146,6 @@ export function ToolbarTermGraph() { title='Граф ступеней' onClick={handleShowTypeGraph} /> - } - title='Сохранить изображение' - onClick={handleSaveImage} - />