Merge pull request 'add-columns-spod-4-form' (#176) from add-columns-spod-4-form into test

Reviewed-on: #176
This commit is contained in:
PotapovaA 2026-09-24 15:11:46 +03:00
commit e01c0c105f
9 changed files with 5517 additions and 5297 deletions

62
web/package-lock.json generated
View File

@ -84,19 +84,6 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-module-imports": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
"integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
"license": "MIT",
"dependencies": {
"@babel/traverse": "^7.29.7",
"@babel/types": "^7.29.7"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": { "node_modules/@babel/helper-string-parser": {
"version": "7.29.7", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
@ -153,24 +140,6 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/traverse": {
"version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz",
"integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==",
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.29.7",
"@babel/generator": "^7.29.7",
"@babel/helper-globals": "^7.29.7",
"@babel/parser": "^7.29.7",
"@babel/template": "^7.29.7",
"@babel/types": "^7.29.7",
"debug": "^4.3.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.29.7", "version": "7.29.7",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz",
@ -423,6 +392,37 @@
"stylis": "4.2.0" "stylis": "4.2.0"
} }
}, },
"node_modules/@emotion/babel-plugin/node_modules/@babel/helper-module-imports": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
"integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
"license": "MIT",
"dependencies": {
"@babel/traverse": "^7.27.1",
"@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@emotion/babel-plugin/node_modules/@babel/traverse": {
"version": "7.28.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz",
"integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==",
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5",
"@babel/helper-globals": "^7.28.0",
"@babel/parser": "^7.28.5",
"@babel/template": "^7.27.2",
"@babel/types": "^7.28.5",
"debug": "^4.3.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@emotion/cache": { "node_modules/@emotion/cache": {
"version": "11.14.0", "version": "11.14.0",
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz",

View File

@ -32,5 +32,9 @@
"daisyui": "^4.12.10", "daisyui": "^4.12.10",
"tailwindcss": "^3.4.13", "tailwindcss": "^3.4.13",
"typescript": "^5.7.3" "typescript": "^5.7.3"
},
"overrides": {
"@babel/helper-module-imports": "7.27.1",
"@babel/traverse": "7.28.5"
} }
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,14 @@ const RealtimeConnectionContext = createContext(null);
const RealtimeVspOptionsContext = createContext(null); const RealtimeVspOptionsContext = createContext(null);
const LockedCellsStoreContext = createContext(null); const LockedCellsStoreContext = createContext(null);
const getColumnRequestKey = (column) => {
const columnKey = column?.columnDef?.id ?? column?.id;
if (columnKey === null || columnKey === undefined) return '';
const normalizedColumnKey = String(columnKey);
return normalizedColumnKey.startsWith('data.') ? normalizedColumnKey.slice(5) : normalizedColumnKey;
};
const useRequiredContext = (context, hookName) => { const useRequiredContext = (context, hookName) => {
const value = useContext(context); const value = useContext(context);
if (value === null) { if (value === null) {
@ -238,21 +246,19 @@ export const RealtimeProvider = ({ children, formId, sheetName, direction, year,
// Функция для начала редактирования ячейки // Функция для начала редактирования ячейки
const startEditing = useCallback( const startEditing = useCallback(
(row, column) => { (row, column) => {
const columnId = column.id;
if (!isConnectedRef.current) { if (!isConnectedRef.current) {
onErrorRef.current?.('WebSocket не подключен'); onErrorRef.current?.('WebSocket не подключен');
return false; return false;
} }
const lineId = row.id || null; const lineId = row.id || null;
const colId = columnId.slice(5); // убираем префикс "data." const columnKey = getColumnRequestKey(column);
const message = { const message = {
event: 'cell_edit_start', event: 'cell_edit_start',
data: { data: {
line_id: lineId, line_id: lineId,
column: colId, column: columnKey,
}, },
}; };
@ -269,21 +275,19 @@ export const RealtimeProvider = ({ children, formId, sheetName, direction, year,
// Функция для завершения редактирования ячейки // Функция для завершения редактирования ячейки
const endEditing = useCallback( const endEditing = useCallback(
(row, column) => { (row, column) => {
const columnId = column.id;
if (!isConnectedRef.current) { if (!isConnectedRef.current) {
onErrorRef.current?.('WebSocket не подключен'); onErrorRef.current?.('WebSocket не подключен');
return false; return false;
} }
const lineId = row.id || null; const lineId = row.id || null;
const colId = columnId.slice(5); const columnKey = getColumnRequestKey(column);
const message = { const message = {
event: 'cell_edit_end', event: 'cell_edit_end',
data: { data: {
line_id: lineId, line_id: lineId,
column: colId, column: columnKey,
}, },
}; };
@ -299,20 +303,19 @@ export const RealtimeProvider = ({ children, formId, sheetName, direction, year,
const updateCell = useCallback( const updateCell = useCallback(
(row, column, value) => { (row, column, value) => {
const columnId = column.id;
if (!isConnectedRef.current) { if (!isConnectedRef.current) {
onErrorRef.current?.('WebSocket не подключен'); onErrorRef.current?.('WebSocket не подключен');
return false; return false;
} }
const lineId = getRowId(row); const lineId = getRowId(row);
const colId = columnId.slice(5); const columnKey = getColumnRequestKey(column);
const message = { const message = {
event: 'cell_updated', event: 'cell_updated',
data: { data: {
line_id: lineId, line_id: lineId,
line_id_code: row.id, line_id_code: row.id,
column: colId, column: columnKey,
value: value, value: value,
}, },
}; };

View File

@ -1,6 +1,6 @@
import { useCallback, useEffect, useState } from 'react'; import { useCallback, useEffect, useState } from 'react';
import { columnPinningDefault, columnVisibilityDefault } from '../constants/columnConfig.js'; import { columnPinningDefault, columnVisibilityDefault } from '../constants/columnConfig.js';
import { collectLeafColumns, getLeafColumns } from '../utils/columnUtils'; import { collectLeafColumns, getColumnKey, getLeafColumns } from '../utils/columnUtils';
import { loadFromStorage, saveToStorage } from '../utils/localStorageUtils.js'; import { loadFromStorage, saveToStorage } from '../utils/localStorageUtils.js';
export const useColumnSettings = (tableKey) => { export const useColumnSettings = (tableKey) => {
@ -62,7 +62,8 @@ export const useColumnSettings = (tableKey) => {
const handleToggleColumnVisibility = useCallback((column, isSelect) => { const handleToggleColumnVisibility = useCallback((column, isSelect) => {
const leafCols = collectLeafColumns(column).reduce((acc, item) => { const leafCols = collectLeafColumns(column).reduce((acc, item) => {
acc[item.id] = isSelect; const columnKey = getColumnKey(item);
if (columnKey) acc[columnKey] = isSelect;
return acc; return acc;
}, {}); }, {});

View File

@ -1,5 +1,5 @@
// Получение accessorKey колонки // Явный id определяет технический ключ колонки; accessorKey используется как fallback.
export const getColumnKey = (node) => node?.accessorKey; export const getColumnKey = (node) => node?.id ?? node?.accessorKey;
// Проверка, нужно ли скрыть колонку из дерева // Проверка, нужно ли скрыть колонку из дерева
export const shouldExcludeFromTree = (node, excludeSet) => { export const shouldExcludeFromTree = (node, excludeSet) => {

View File

@ -3,7 +3,7 @@ import { CheckBox, CheckBoxOutlineBlank, IndeterminateCheckBox } from '@mui/icon
import { Box, Checkbox, InputAdornment, Popover, TextField, Typography } from '@mui/material'; import { Box, Checkbox, InputAdornment, Popover, TextField, Typography } from '@mui/material';
import { SimpleTreeView, TreeItem } from '@mui/x-tree-view'; import { SimpleTreeView, TreeItem } from '@mui/x-tree-view';
import { memo, useMemo, useState } from 'react'; import { memo, useMemo, useState } from 'react';
import { filterColumnTree, getColumnTreeLeafKeys } from '../RealtimeTable/utils/columnUtils'; import { filterColumnTree, getColumnKey, getColumnTreeLeafKeys } from '../RealtimeTable/utils/columnUtils';
import { formatHeaderYear } from '../RealtimeTable/utils/headerYearUtils'; import { formatHeaderYear } from '../RealtimeTable/utils/headerYearUtils';
const EMPTY_IDS = []; const EMPTY_IDS = [];
@ -62,7 +62,7 @@ const CollapsibleTree = ({
}; };
const leafColumns = getLeafColumn(node); const leafColumns = getLeafColumn(node);
return leafColumns.map((c) => c.id || c.accessorKey); return leafColumns.map(getColumnKey).filter(Boolean);
}; };
const isNodeChecked = (node) => { const isNodeChecked = (node) => {
@ -84,11 +84,11 @@ const CollapsibleTree = ({
let current = column; let current = column;
while (current) { while (current) {
ancestors.unshift(current.id || current.accessorKey); ancestors.unshift(getColumnKey(current));
current = current.parent; current = current.parent;
} }
return ancestors; return ancestors.filter(Boolean);
}; };
return getFullColumnPath(column).join('_'); return getFullColumnPath(column).join('_');
}; };
@ -98,9 +98,10 @@ const CollapsibleTree = ({
return nodes.map((node) => { return nodes.map((node) => {
const checkStatus = isNodeChecked(node); const checkStatus = isNodeChecked(node);
const nodeKey = getColumnKey(node);
return ( return (
<TreeItem <TreeItem
key={node.id || node.accessorKey} key={nodeKey}
itemId={String(getId(node))} itemId={String(getId(node))}
label={ label={
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}> <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>