исправила иерархию, блокировка ячеек, виртуализация строк
This commit is contained in:
parent
fcece07c64
commit
56833f454b
@ -1,7 +1,8 @@
|
|||||||
import React from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useRealtime } from '../../contexts/RealtimeContext';
|
import { useRealtime } from '../../contexts/RealtimeContext';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
|
||||||
|
|
||||||
const ContainerForText = styled.span`
|
const ContainerForText = styled.span`
|
||||||
@ -42,7 +43,7 @@ const highlightText = (text, searchQuery) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Cell = React.memo(({ cell, row, column, onClick, globalFilter, backgroundColor, color }) => {
|
const Cell = React.memo(({ cell, row, column, onClick, globalFilter, backgroundColor, color, isEditable }) => {
|
||||||
const cellValue = cell.getValue();
|
const cellValue = cell.getValue();
|
||||||
const textValue = String(cellValue || '');
|
const textValue = String(cellValue || '');
|
||||||
|
|
||||||
@ -51,14 +52,11 @@ const Cell = React.memo(({ cell, row, column, onClick, globalFilter, backgroundC
|
|||||||
return highlightText(textValue, globalFilter);
|
return highlightText(textValue, globalFilter);
|
||||||
}, [textValue, globalFilter]);
|
}, [textValue, globalFilter]);
|
||||||
|
|
||||||
const {
|
const lockedStyles = !isEditable ? {
|
||||||
isCellLocked,
|
border: '2px solid #d3d3d3',
|
||||||
getCellLockInfo,
|
color: '#525252',
|
||||||
updateCell,
|
cursor: 'not-allowed',
|
||||||
subscribeToErrors,
|
} : {};
|
||||||
tryLockCell,
|
|
||||||
unlockCell
|
|
||||||
} = useRealtime();
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -80,6 +78,7 @@ const Cell = React.memo(({ cell, row, column, onClick, globalFilter, backgroundC
|
|||||||
padding: '8px',
|
padding: '8px',
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: backgroundColor,
|
||||||
color: color,
|
color: color,
|
||||||
|
...lockedStyles
|
||||||
}}
|
}}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -7,7 +7,7 @@ const EditCell = ({ refCell, onChange, disabled, value }) => {
|
|||||||
const left = tdFrag.offsetLeft;
|
const left = tdFrag.offsetLeft;
|
||||||
const width = refCell.current.offsetParent.offsetWidth;
|
const width = refCell.current.offsetParent.offsetWidth;
|
||||||
|
|
||||||
const translateY = 'translateY(' + trFrag.offsetTop + 'px)';
|
const translateY = trFrag.style.transform;
|
||||||
|
|
||||||
function useAutoResize(value) {
|
function useAutoResize(value) {
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
// components/RealtimeTable/index.js
|
// components/RealtimeTable/index.js
|
||||||
import React, { useState, useMemo, useRef, useEffect, useCallback } from 'react';
|
import React, { useState, useMemo, useRef, useEffect, useCallback, useTransition } from 'react';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import {
|
import {
|
||||||
useMaterialReactTable,
|
useMaterialReactTable,
|
||||||
@ -25,12 +25,18 @@ import { toast } from 'react-toastify';
|
|||||||
|
|
||||||
const RealtimeTable = ({ formType, formId, sheetName, direction }) => {
|
const RealtimeTable = ({ formType, formId, sheetName, direction }) => {
|
||||||
const { data, setData } = useRealtimeData(formId, sheetName, direction);
|
const { data, setData } = useRealtimeData(formId, sheetName, direction);
|
||||||
const [isLoading, setIsLoading] = useState(true);
|
|
||||||
const [globalFilter, setGlobalFilter] = useState('');
|
const [globalFilter, setGlobalFilter] = useState('');
|
||||||
const [showColumnFilters, setShowColumnFilters] = useState(false);
|
const [showColumnFilters, setShowColumnFilters] = useState(false);
|
||||||
const [selectedColumn, setSelectedColumn] = useState();
|
const [selectedColumn, setSelectedColumn] = useState();
|
||||||
const columnVirtualizerInstanceRef = useRef(null);
|
|
||||||
const [rowSelection, setRowSelection] = useState({});
|
const [rowSelection, setRowSelection] = useState({});
|
||||||
|
const [isLoadingData, setIsLoadingData] = useState(false);
|
||||||
|
const [isPending, startTransition] = useTransition();
|
||||||
|
|
||||||
|
const handleGlobalFilterChange = (value) => {
|
||||||
|
startTransition(() => {
|
||||||
|
setGlobalFilter(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
isConnected,
|
isConnected,
|
||||||
@ -85,7 +91,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction }) => {
|
|||||||
setRowSelection((prev) => ({
|
setRowSelection((prev) => ({
|
||||||
[rowId]: !prev[rowId],
|
[rowId]: !prev[rowId],
|
||||||
}));
|
}));
|
||||||
}, [rowSelection])
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
const columns = useMemo(() => {
|
const columns = useMemo(() => {
|
||||||
@ -108,7 +114,6 @@ const RealtimeTable = ({ formType, formId, sheetName, direction }) => {
|
|||||||
}
|
}
|
||||||
}, [columnsConfig, handleUpdateCell]);
|
}, [columnsConfig, handleUpdateCell]);
|
||||||
|
|
||||||
|
|
||||||
const tableMeta = useMemo(() => ({
|
const tableMeta = useMemo(() => ({
|
||||||
updateCell: handleUpdateCell,
|
updateCell: handleUpdateCell,
|
||||||
}), [handleUpdateCell]);
|
}), [handleUpdateCell]);
|
||||||
@ -119,13 +124,17 @@ const RealtimeTable = ({ formType, formId, sheetName, direction }) => {
|
|||||||
...BASE_TABLE_CONFIG,
|
...BASE_TABLE_CONFIG,
|
||||||
columns,
|
columns,
|
||||||
data: data,
|
data: data,
|
||||||
columnVirtualizerInstanceRef,
|
enableRowVirtualization: true,
|
||||||
enableRowVirtualization: false,
|
rowVirtualizerOptions: {
|
||||||
|
overscan: 50,
|
||||||
|
scrollPaddingStart: 0,
|
||||||
|
scrollPaddingEnd: 0,
|
||||||
|
},
|
||||||
enableRowSelection: true,
|
enableRowSelection: true,
|
||||||
onRowSelectionChange: setRowSelection,
|
onRowSelectionChange: setRowSelection,
|
||||||
onColumnSizingChange: setColumnSizing,
|
onColumnSizingChange: setColumnSizing,
|
||||||
onColumnPinningChange: setColumnPinning,
|
onColumnPinningChange: setColumnPinning,
|
||||||
onGlobalFilterChange: setGlobalFilter,
|
onGlobalFilterChange: handleGlobalFilterChange,
|
||||||
state: {
|
state: {
|
||||||
columnSizing,
|
columnSizing,
|
||||||
columnPinning,
|
columnPinning,
|
||||||
@ -135,7 +144,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction }) => {
|
|||||||
rowSelection
|
rowSelection
|
||||||
},
|
},
|
||||||
initialState: {
|
initialState: {
|
||||||
hiddenColumn: []
|
expanded: true
|
||||||
},
|
},
|
||||||
meta: tableMeta,
|
meta: tableMeta,
|
||||||
muiTableHeadCellProps: ({ column }) => ({
|
muiTableHeadCellProps: ({ column }) => ({
|
||||||
@ -153,22 +162,13 @@ const RealtimeTable = ({ formType, formId, sheetName, direction }) => {
|
|||||||
height: '1px',
|
height: '1px',
|
||||||
minHeight: '1px',
|
minHeight: '1px',
|
||||||
maxHeight: '1px',
|
maxHeight: '1px',
|
||||||
opacity: 0,
|
visibility: 'hidden',
|
||||||
pointerEvents: 'none',
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
'& th': {
|
|
||||||
height: '1px',
|
|
||||||
minHeight: '1px',
|
|
||||||
maxHeight: '1px',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
muiTablePaperProps: getTablePaperStyles(),
|
muiTablePaperProps: getTablePaperStyles(),
|
||||||
muiTableContainerProps: {
|
muiTableContainerProps: {
|
||||||
ref: containerRef,
|
ref: containerRef,
|
||||||
sx: {
|
sx: {
|
||||||
overflowX: 'auto',
|
|
||||||
overflowY: 'auto',
|
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
contain: 'layout',
|
contain: 'layout',
|
||||||
minHeight: '100%',
|
minHeight: '100%',
|
||||||
@ -198,6 +198,12 @@ const RealtimeTable = ({ formType, formId, sheetName, direction }) => {
|
|||||||
|
|
||||||
const table = useMaterialReactTable(tableConfig);
|
const table = useMaterialReactTable(tableConfig);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (table && data && columns.length !== 0) {
|
||||||
|
setIsLoadingData(true)
|
||||||
|
}
|
||||||
|
}, [data, columns, table])
|
||||||
|
|
||||||
const handleAddRow = useCallback(() => {
|
const handleAddRow = useCallback(() => {
|
||||||
const allRows = table.getRowModel().rows;
|
const allRows = table.getRowModel().rows;
|
||||||
|
|
||||||
@ -222,7 +228,9 @@ const RealtimeTable = ({ formType, formId, sheetName, direction }) => {
|
|||||||
const row = selectedRows[0];
|
const row = selectedRows[0];
|
||||||
const expense_item_id = row.original.data.line_id;
|
const expense_item_id = row.original.data.line_id;
|
||||||
contextDeleteRow(expense_item_id)
|
contextDeleteRow(expense_item_id)
|
||||||
|
setRowSelection({});
|
||||||
}, [rowSelection, table])
|
}, [rowSelection, table])
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return <div>Загрузка...</div>;
|
return <div>Загрузка...</div>;
|
||||||
}
|
}
|
||||||
@ -237,11 +245,12 @@ const RealtimeTable = ({ formType, formId, sheetName, direction }) => {
|
|||||||
onToggleColumnVisibility={handleToggleColumnVisibility}
|
onToggleColumnVisibility={handleToggleColumnVisibility}
|
||||||
columnVisibility={columnVisibility}
|
columnVisibility={columnVisibility}
|
||||||
onChangeSizeMult={setSizeMult}
|
onChangeSizeMult={setSizeMult}
|
||||||
onGlobalFilterChange={setGlobalFilter}
|
onGlobalFilterChange={handleGlobalFilterChange}
|
||||||
sizeMult={sizeMult}
|
sizeMult={sizeMult}
|
||||||
onChangeShowColumnFilters={setShowColumnFilters}
|
onChangeShowColumnFilters={setShowColumnFilters}
|
||||||
onAddRow={handleAddRow}
|
onAddRow={handleAddRow}
|
||||||
onDeleteRow={handleDeleteRow}
|
onDeleteRow={handleDeleteRow}
|
||||||
|
isLoadingData={isLoadingData}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div style={tableWrapperStyle}>
|
<div style={tableWrapperStyle}>
|
||||||
@ -265,6 +274,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction }) => {
|
|||||||
onHeaderSelect={setSelectedColumn}
|
onHeaderSelect={setSelectedColumn}
|
||||||
selectHeader={selectedColumn}
|
selectHeader={selectedColumn}
|
||||||
onChangeWidth={handleSetColumnWidth}
|
onChangeWidth={handleSetColumnWidth}
|
||||||
|
isLoadingData={isLoadingData}
|
||||||
/>,
|
/>,
|
||||||
headerPortalRef.current,
|
headerPortalRef.current,
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -31,6 +31,7 @@ const SettingPanel = ({
|
|||||||
onChangeShowColumnFilters,
|
onChangeShowColumnFilters,
|
||||||
onAddRow,
|
onAddRow,
|
||||||
onDeleteRow,
|
onDeleteRow,
|
||||||
|
isLoadingData,
|
||||||
}) => {
|
}) => {
|
||||||
const [isPinned, setIsPinned] = useState(false);
|
const [isPinned, setIsPinned] = useState(false);
|
||||||
const [columnTree, setColumnTree] = useState();
|
const [columnTree, setColumnTree] = useState();
|
||||||
@ -41,7 +42,7 @@ const SettingPanel = ({
|
|||||||
if (!table) return;
|
if (!table) return;
|
||||||
setColumnTree(table.getAllColumns());
|
setColumnTree(table.getAllColumns());
|
||||||
setShowColumnFilters(table.getState().showColumnFilters);
|
setShowColumnFilters(table.getState().showColumnFilters);
|
||||||
}, [table]);
|
}, [table, isLoadingData]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!selectedColumn) return;
|
if (!selectedColumn) return;
|
||||||
|
|||||||
@ -131,7 +131,6 @@ const HeaderCell = ({ header, table, onClick, hightlight, onChangeWidth }) => {
|
|||||||
// Если колонка не закреплена, текст должен начинаться после всех закрепленных колонок
|
// Если колонка не закреплена, текст должен начинаться после всех закрепленных колонок
|
||||||
const getTextLeftOffset = () => {
|
const getTextLeftOffset = () => {
|
||||||
if (isPinned) {
|
if (isPinned) {
|
||||||
// Для закрепленных колонок текст остается на месте
|
|
||||||
return '0';
|
return '0';
|
||||||
}
|
}
|
||||||
// Для незакрепленных колонок текст должен начинаться после всех закрепленных
|
// Для незакрепленных колонок текст должен начинаться после всех закрепленных
|
||||||
@ -215,7 +214,7 @@ const FilterRow = ({ table }) => {
|
|||||||
style={{
|
style={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
position: 'sticky',
|
position: 'sticky',
|
||||||
top: '1.5rem', // После строки с номерами колонок
|
top: '1.5rem',
|
||||||
zIndex: 20,
|
zIndex: 20,
|
||||||
backgroundColor: 'white',
|
backgroundColor: 'white',
|
||||||
}}
|
}}
|
||||||
@ -338,11 +337,16 @@ export const TableHead = ({
|
|||||||
onHeaderSelect,
|
onHeaderSelect,
|
||||||
selectHeader,
|
selectHeader,
|
||||||
onChangeWidth,
|
onChangeWidth,
|
||||||
|
isLoadingData,
|
||||||
}) => {
|
}) => {
|
||||||
const handleHeaderClick = (header) => {
|
const handleHeaderClick = (header) => {
|
||||||
onHeaderSelect(header);
|
onHeaderSelect(header);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!isLoadingData) {
|
||||||
|
return <div></div>
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@ -86,15 +86,8 @@ const useRealtimeData = (formId, sheetName, direction) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxDepth = data.reduce(
|
const hierarchicalData = buildHierarchy(data);
|
||||||
(prev, current) => {
|
setData(hierarchicalData);
|
||||||
return (prev.depth || 0) > (current.depth || 0) ? prev : current;
|
|
||||||
},
|
|
||||||
{ depth: 0 },
|
|
||||||
).depth;
|
|
||||||
|
|
||||||
const formattedData = formatedToSubRows(maxDepth, data);
|
|
||||||
setData(formattedData);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to load initial data:", err);
|
console.error("Failed to load initial data:", err);
|
||||||
setError(err.message);
|
setError(err.message);
|
||||||
@ -104,7 +97,54 @@ const useRealtimeData = (formId, sheetName, direction) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
loadInitialData();
|
loadInitialData();
|
||||||
}, [formId, sheetName, formatedToSubRows]);
|
}, [formId, sheetName]);
|
||||||
|
|
||||||
|
const buildHierarchy = (items) => {
|
||||||
|
const result = [];
|
||||||
|
const stack = [];
|
||||||
|
|
||||||
|
const getTypeLevel = (type) => {
|
||||||
|
const levels = {
|
||||||
|
ROOT: 0,
|
||||||
|
GROUP: 1,
|
||||||
|
ITEM: 2,
|
||||||
|
SUB_ITEM: 3,
|
||||||
|
INPUT: 4,
|
||||||
|
};
|
||||||
|
return levels[type] ?? 999;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const item of items) {
|
||||||
|
const currentLevel = getTypeLevel(item.row_type);
|
||||||
|
|
||||||
|
while (
|
||||||
|
stack.length > 0 &&
|
||||||
|
getTypeLevel(stack[stack.length - 1].row_type) >= currentLevel
|
||||||
|
) {
|
||||||
|
stack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
const parent = stack.length > 0 ? stack[stack.length - 1] : null;
|
||||||
|
|
||||||
|
const newNode = { ...item, subRows: [] };
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
if (!parent.subRows) {
|
||||||
|
parent.subRows = [];
|
||||||
|
}
|
||||||
|
parent.subRows.push(newNode);
|
||||||
|
} else {
|
||||||
|
result.push(newNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавляем текущий узел в стек, если он может иметь детей
|
||||||
|
if (item.row_type !== "INPUT") {
|
||||||
|
stack.push(newNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIsConnected(wsConnected);
|
setIsConnected(wsConnected);
|
||||||
|
|||||||
@ -9,7 +9,8 @@ function EditCellPortal({
|
|||||||
EditCell,
|
EditCell,
|
||||||
onSaveStart,
|
onSaveStart,
|
||||||
onSaveEnd,
|
onSaveEnd,
|
||||||
onError
|
onError,
|
||||||
|
isEditable
|
||||||
}) {
|
}) {
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
const [refTbody, setRefTbody] = useState(false);
|
const [refTbody, setRefTbody] = useState(false);
|
||||||
@ -25,17 +26,7 @@ function EditCellPortal({
|
|||||||
|
|
||||||
const handleChange = async (val) => {
|
const handleChange = async (val) => {
|
||||||
table.setEditingCell(null);
|
table.setEditingCell(null);
|
||||||
if (isSaving) return;
|
|
||||||
|
|
||||||
setIsSaving(true);
|
|
||||||
onSaveStart?.();
|
|
||||||
|
|
||||||
// Сохраняем старое значение на случай ошибки
|
|
||||||
const oldValue = cell.getValue();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
// Используем updateCell из контекста (передается через meta)
|
|
||||||
if (table.options.meta?.updateCell) {
|
if (table.options.meta?.updateCell) {
|
||||||
const success = await table.options.meta.updateCell(
|
const success = await table.options.meta.updateCell(
|
||||||
cell.row,
|
cell.row,
|
||||||
@ -44,32 +35,15 @@ function EditCellPortal({
|
|||||||
);
|
);
|
||||||
if (success) {
|
if (success) {
|
||||||
console.log('Cell updated successfully via WebSocket');
|
console.log('Cell updated successfully via WebSocket');
|
||||||
onSaveEnd?.(true);
|
|
||||||
table.setEditingCell(null);
|
|
||||||
} else {
|
} else {
|
||||||
console.error('Failed to update cell via WebSocket');
|
console.error('Failed to update cell via WebSocket');
|
||||||
const errorMsg = 'Не удалось сохранить изменение';
|
const errorMsg = 'Не удалось сохранить изменение';
|
||||||
onError?.(errorMsg);
|
onError?.(errorMsg);
|
||||||
onSaveEnd?.(false);
|
|
||||||
// Возвращаем предыдущее значение
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Если updateCell нет в meta, используем onCellUpdate из пропсов (fallback)
|
|
||||||
console.warn('WebSocket updateCell not configured in meta');
|
|
||||||
if (table.options.meta?.onCellUpdate) {
|
|
||||||
table.options.meta.onCellUpdate(cell.row.id, cell.column.id, val);
|
|
||||||
}
|
|
||||||
onSaveEnd?.(true);
|
|
||||||
table.setEditingCell(null);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error updating cell:', error);
|
console.error('Error updating cell:', error);
|
||||||
onError?.(error.message);
|
onError?.(error.message);
|
||||||
onSaveEnd?.(false);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
setIsSaving(false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -88,7 +62,7 @@ function EditCellPortal({
|
|||||||
refCell={ref}
|
refCell={ref}
|
||||||
cell={cell}
|
cell={cell}
|
||||||
value={cell.getValue()}
|
value={cell.getValue()}
|
||||||
disabled={isDisabled || isSaving}
|
disabled={!isEditable}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
/>,
|
/>,
|
||||||
refTbody,
|
refTbody,
|
||||||
@ -131,8 +105,9 @@ export const getTableColumns = ({
|
|||||||
column={column}
|
column={column}
|
||||||
cell={cell}
|
cell={cell}
|
||||||
globalFilter={
|
globalFilter={
|
||||||
table.getState().globalFilter || column.getFilterValue()
|
table.getState().globalFilter
|
||||||
}
|
}
|
||||||
|
isEditable={row.original?.row_type === 'INPUT' || false}
|
||||||
backgroundColor={columnColors[column.id]?.color_type?.[row.original?.row_type || row.row_type]}
|
backgroundColor={columnColors[column.id]?.color_type?.[row.original?.row_type || row.row_type]}
|
||||||
color={columnColors[column.id]?.color_type?.['COLOR']}
|
color={columnColors[column.id]?.color_type?.['COLOR']}
|
||||||
isUpdating={table.options.meta?.updatingCells?.[`${row.id}_${column.id}`]}
|
isUpdating={table.options.meta?.updatingCells?.[`${row.id}_${column.id}`]}
|
||||||
@ -144,20 +119,8 @@ export const getTableColumns = ({
|
|||||||
cell={cell}
|
cell={cell}
|
||||||
table={table}
|
table={table}
|
||||||
EditCell={EditCell}
|
EditCell={EditCell}
|
||||||
onSaveStart={() => {
|
|
||||||
if (table.options.meta?.setUpdatingCell) {
|
|
||||||
table.options.meta.setUpdatingCell(row.id, column.id, true);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onSaveEnd={(success) => {
|
|
||||||
if (table.options.meta?.setUpdatingCell) {
|
|
||||||
table.options.meta.setUpdatingCell(row.id, column.id, false);
|
|
||||||
}
|
|
||||||
if (!success && onCellUpdateError) {
|
|
||||||
onCellUpdateError(row.id, column.id, 'Failed to save');
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onError={onCellUpdateError}
|
onError={onCellUpdateError}
|
||||||
|
isEditable={row.original?.row_type === 'INPUT' || false}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -177,10 +140,9 @@ export const getTableColumns = ({
|
|||||||
enableEditing: false,
|
enableEditing: false,
|
||||||
enablePinning: true,
|
enablePinning: true,
|
||||||
Cell: ({ cell, row }) => {
|
Cell: ({ cell, row }) => {
|
||||||
return <span
|
return <button onClick={() => { console.log('TEST', row.id); onCellNumberClick(row.id) }}>
|
||||||
|
{cell.getValue()}
|
||||||
onClick={() => {console.log('TEST', row.id); onCellNumberClick(row.id)}}
|
</button>
|
||||||
>{cell.getValue()}</span>;
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
export function setNewValueToData(data, colId, rowId, value) {
|
export function setNewValueToData(data, colId, rowId, value) {
|
||||||
// 1. Находим целевой объект по rowId(индексы вложенных subRows)
|
|
||||||
let targetObject = data;
|
let targetObject = data;
|
||||||
if (rowId && rowId.length) {
|
if (rowId && rowId.length) {
|
||||||
const indices = rowId.split(".").map(Number);
|
const indices = rowId.split(".").map(Number);
|
||||||
|
|||||||
@ -14,7 +14,7 @@ const TableCard = ({ table, onNavigate }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={table}>
|
<div key={table.sheet + '_' + table?.direction}>
|
||||||
<Section onClick={handleClick}>
|
<Section onClick={handleClick}>
|
||||||
<SectionStartPart>
|
<SectionStartPart>
|
||||||
<div className="for-img-table">
|
<div className="for-img-table">
|
||||||
|
|||||||
@ -26,7 +26,7 @@ const TablesList = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<TableCard
|
<TableCard
|
||||||
key={table.sheet}
|
key={table.sheet+"_"+table?.direction}
|
||||||
onNavigate={() => handleNavigate(path)}
|
onNavigate={() => handleNavigate(path)}
|
||||||
table={table}
|
table={table}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user