fixies-3-form #105

Merged
PotapovaA merged 4 commits from fixies-3-form into test 2026-08-19 18:39:11 +03:00
4 changed files with 86 additions and 22 deletions
Showing only changes of commit d347023211 - Show all commits

View File

@ -163,6 +163,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
handleUnpinColumn,
handleSetColumnWidth,
handleToggleColumnVisibility,
handleSetColumnsVisibility,
} = useColumnSettings(`${formId}_${formType}_${sheetName}_${direction}`);
const { headerPortalRef, containerRef } = useHeaderPortal();
@ -174,6 +175,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
useEffect(() => {
rowVirtualizerRef.current?.measure?.();
columnVirtualizerRef.current?.measure?.();
}, [sizeMult]);
useEffect(() => {
@ -300,10 +302,7 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
}, [columns, columnPinning, columnSizing, columnVisibility]);
const selectedColumnIdRef = useRef(selectedColumnId);
useEffect(() => {
selectedColumnIdRef.current = selectedColumnId;
}, [selectedColumnId]);
selectedColumnIdRef.current = selectedColumnId;
const tableMeta = useMemo(() => ({
updateCell: handleUpdateCell,
@ -610,13 +609,13 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
return (
<>
<SettingsPanel
selectedColumnId={selectedColumnId}
columnPinning={columnPinning}
table={table}
columns={columns}
selectedColumnId={selectedColumnId}
columnPinning={columnPinning}
columns={columns}
onPinColumn={handlePinColumn}
onUnpinColumn={handleUnpinColumn}
onToggleColumnVisibility={handleToggleColumnVisibility}
onToggleColumnVisibility={handleToggleColumnVisibility}
onSetColumnsVisibility={handleSetColumnsVisibility}
columnVisibility={columnVisibility}
columnsCurStage={columnsCurStage}
onChangeSizeMult={setSizeMult}
@ -628,7 +627,6 @@ const RealtimeTable = ({ formType, formId, sheetName, direction, year }) => {
onAddProgram={addProgram}
onAddProject={addProject}
onDeleteRow={handleDeleteRow}
isLoadingData={isLoadingData}
formId={formId}
sheetName={sheetName}
direction={direction}

View File

@ -37,11 +37,11 @@ const exportButtonSx = { height: '2.5rem', minHeight: '2.5rem' };
const SettingPanel = ({
selectedColumnId,
columnPinning,
table,
columns,
onPinColumn,
onUnpinColumn,
onToggleColumnVisibility,
onSetColumnsVisibility,
columnVisibility,
columnsCurStage,
onChangeSizeMult,
@ -53,7 +53,6 @@ const SettingPanel = ({
onAddProgram,
onAddProject,
onDeleteRow,
isLoadingData,
formId,
sheetName,
direction,
@ -119,10 +118,12 @@ const SettingPanel = ({
console.warn('Нет столбцов для текущего этапа');
return;
}
const visibilityByColumnId = {};
for (const column of leafColumns) {
onToggleColumnVisibility(column, showOnlyCurrentStageColumns || stageColumnIds.has(column.id));
visibilityByColumnId[column.id] = showOnlyCurrentStageColumns || stageColumnIds.has(column.id);
}
}, [columnsCurStage, leafColumns, onToggleColumnVisibility, showOnlyCurrentStageColumns, stageColumnIds]);
onSetColumnsVisibility(visibilityByColumnId);
}, [columnsCurStage, leafColumns, onSetColumnsVisibility, showOnlyCurrentStageColumns, stageColumnIds]);
return (
<>

View File

@ -3,21 +3,79 @@ import {
useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState,
useSyncExternalStore,
} from "react";
import { toast } from "react-toastify";
import { useWebSocket } from "../hooks/useWebSocket";
import { getRowId } from "../utils/rowUtils";
const RealtimeContext = createContext(null);
const RealtimeActionsContext = createContext(null);
const RealtimeConnectionContext = createContext(null);
const RealtimeVspOptionsContext = createContext(null);
const LockedCellsStoreContext = createContext(null);
const useRequiredContext = (context, hookName) => {
const value = useContext(context);
if (value === null) {
throw new Error(`${hookName} must be used within RealtimeProvider`);
}
return value;
};
const createLockedCellsStore = () => {
let cells = new Set();
const listeners = new Set();
const subscribe = (listener) => {
listeners.add(listener);
return () => listeners.delete(listener);
};
const setCells = (nextValue) => {
const currentCells = [...cells];
const resolvedValue = typeof nextValue === "function" ? nextValue(currentCells) : nextValue;
const nextCells = new Set(resolvedValue || []);
const hasChanges =
nextCells.size !== cells.size || [...nextCells].some((cellKey) => !cells.has(cellKey));
if (!hasChanges) return;
cells = nextCells;
listeners.forEach((listener) => listener());
};
return {
subscribe,
setCells,
hasCell: (cellKey) => cells.has(cellKey),
getCells: () => [...cells],
};
};
export const useRealtimeActions = () =>
useRequiredContext(RealtimeActionsContext, "useRealtimeActions");
export const useRealtimeConnection = () =>
useRequiredContext(RealtimeConnectionContext, "useRealtimeConnection");
export const useVspOptions = () =>
useRequiredContext(RealtimeVspOptionsContext, "useVspOptions");
export const useCellLock = (cellKey) => {
const store = useRequiredContext(LockedCellsStoreContext, "useCellLock");
const getSnapshot = useCallback(() => store.hasCell(cellKey), [cellKey, store]);
return useSyncExternalStore(store.subscribe, getSnapshot, () => false);
};
export const useRealtime = () => {
const context = useContext(RealtimeContext);
if (!context) {
throw new Error("useRealtime must be used within RealtimeProvider");
}
return context;
const actions = useRealtimeActions();
const connection = useRealtimeConnection();
const vspOptions = useVspOptions();
return { ...actions, ...connection, vspOptions };
};
export const RealtimeProvider = ({
@ -41,9 +99,11 @@ export const RealtimeProvider = ({
: `/api/v1/ws/projects/${formId}/report/${year}/${sheetName}`
}`;
//для ячеек которые редактируются другими пользователями
const [lockedCells, setLockedCells] = useState([]);
const [vspOptions, setVspOptions] = useState([]);
const lockedCellsStoreRef = useRef(null);
if (lockedCellsStoreRef.current === null) {
lockedCellsStoreRef.current = createLockedCellsStore();
}
const handleMessage = useCallback((data) => {
// Обработка ошибок

View File

@ -66,6 +66,10 @@ export const useColumnSettings = (tableKey) => {
setColumnVisibility((prev) => ({ ...prev, ...leafCols }));
}, []);
const handleSetColumnsVisibility = useCallback((visibilityByColumnId) => {
setColumnVisibility((prev) => ({ ...prev, ...visibilityByColumnId }));
}, []);
// Опционально: функция для сброса всех настроек
const resetAllSettings = useCallback(() => {
setColumnSizing({});
@ -84,6 +88,7 @@ export const useColumnSettings = (tableKey) => {
handleUnpinColumn,
handleSetColumnWidth,
handleToggleColumnVisibility,
handleSetColumnsVisibility,
resetAllSettings, // добавляем функцию сброса
tableKey, // опционально возвращаем tableKey
};