const { styleId, valueTypeId } = props;
const dispatch = useAppDispatch();
const loading = useAppSelector((state) => state.objectStyleParameter.loading);
const objectStyleParameters = useAppSelector((state) => state.objectStyleParameter.objectStyleParameters);
const error = useAppSelector((state) => state.objectStyleParameter.error);
const standards = useAppSelector((state) => state.standard.standards);
const components = useAppSelector((state) => state.component.components);
const parameterGroups = useAppSelector((state) => state.parameterGroup.parameterGroups);
const parameters = useAppSelector((state) => state.parameter.parameters);
const layers = useAppSelector((state) => state.layer.layers);
const settings = useAppSelector((state) => state.setting.settings);
const objectStyles = useAppSelector((state) => state.objectStyle.objectStyles);
const valueTypes = useAppSelector((state) => state.valueType.valueTypes);
//set the state of the Progress for Importing as well as the state of the Import
const [progress, setProgress] = useState(0);
const [isImporting, setIsImporting] = useState(false);
//Memoizing the expensive computations for the state
//Get the standardId for the current objectStyles and memoize it
const standardId = useMemo(
() => objectStyles.find((style) => style.Id === styleId)?.StandardId,
[objectStyles, styleId]
);
//Create a parameter map and set it for each ValueTypeId
const parameterMap = useMemo(() => {
const map = new Map();
parameters.forEach((pg) => {
if (pg.ValueTypeId === valueTypeId) {
map.set(pg.Id, pg);
}
});
return map;
}, [parameters, valueTypeId]);
//filter the parameters and memoize it
const filteredParameters = useMemo(
() => parameters.filter((p) => p.ValueTypeId === valueTypeId),
[parameters, valueTypeId]
);
//filter ObjectStyleParameters and memoize them
const { filteredStyleParameters } = useMemo(
() => filterStyleParametersByStyleAndParameterMap(objectStyleParameters, parameterMap, styleId),
[objectStyleParameters, parameterMap, styleId]
);
const filteredStyleParametersByValueType = useMemo(
() => objectStyleParameters.filter((styleParameter) => parameterMap.has(styleParameter.ParameterId)),
[objectStyleParameters, parameterMap]
);
const sortedStyleComponents = sortModels(components, 'Name');
const sortedParameterGroups = sortModels(parameterGroups, 'Name');
const sortedParameters = sortModels(filteredParameters, 'Name');
//This sets the errors in the current handsontable instance
const [validationErrors, setValidationErrors] = useState<Error[]>([]);
const [changesMade, setChangesMade] = useState<boolean | undefined>(undefined);
const [open, setOpen] = useState(false);
//Create a dropdown Standard State that gets updated when we select a different Standard from the dropdown
const [dropdownStandardId, setDropdownStandardId] = useState<string>(standardId || '');
//Updates Dropdown ObjectStyles according to Standard
const [dropdownStyles, setDropdownStyles] = useState<ObjectStyle[]>([]);
function sortModels<T>(models: T[], property: keyof T): T[] {
return [...models].sort((a, b) => {
const textA = String(a[property]).toUpperCase();
const textB = String(b[property]).toUpperCase();
return textA.localeCompare(textB);
});
}
const sortedStyles = sortModels(objectStyles, 'Name');
const sortedLayers = sortModels(layers, 'Name');
const handleImportClickOption = () => {
setOpen(true);
};
const handleImportCloseOption = () => {
setOpen(false);
};
const hotTableObjectStyleParameterRef = useRef<HotTable>(null);
function getExtendedParameterName(parameter: Parameter): string {
let extendedName = parameter.Name + ' (' + parameter.ValueTypeId + ')';
return extendedName;
}
const layerMap = new Map(layers.map((l) => [l.Id, l.Name]));
const styleMap = new Map(objectStyles.map((s) => [s.Id, s.Name]));
function getLayerName(layerId: string | undefined) {
if (!layerId) return '';
return layerMap.get(layerId) || '';
}
function getStyleName(styleId: string) {
if (!styleId) return '';
return styleMap.get(styleId) || '';
}
const getParameterName = (parameters: Parameter[], parameterId: string | undefined) => {
const parameter = parameters.find((p) => p.Id === parameterId);
return parameter ? getExtendedParameterName(parameter) : '';
};
//Updates the handsontable instance with all the ObjectStyleParameters from all ObjectStyles
const handleImportClick = async () => {
const selectedIds = CheckboxStateManager.getSelectedIds();
setIsImporting(true);
setProgress(0);
//Create maps for all the models that we need to lookup
const parameterMap = new Map(parameters.map((p) => [p.Id, p]));
const componentMap = new Map(components.map((c) => [c.Id, c.Name]));
const parameterGroupMap = new Map(parameterGroups.map((pg) => [pg.Id, pg.Name]));
const groupsToAdd = [];
for (const selectedId of selectedIds) {
for (const objectStyleParameter of objectStyleParameters) {
if (
objectStyleParameter.ObjectStyleId === selectedId &&
parameterMap.has(objectStyleParameter.ParameterId) &&
parameterMap.get(objectStyleParameter.ParameterId)?.ValueTypeId === valueTypeId
) {
let copy = {
...objectStyleParameter,
StyleComponentName:
componentMap.get(objectStyleParameter.StyleComponentId) || objectStyleParameter.StyleComponentName,
ParameterName:
getParameterName(parameters, objectStyleParameter.ParameterId) || objectStyleParameter.ParameterName,
ParameterGroupName:
parameterGroupMap.get(objectStyleParameter.ParameterGroupId) || objectStyleParameter.ParameterGroupName,
};
const parameter = parameterMap.get(copy.ParameterId);
if (parameter?.ValueTypeId === VALUETYPES.Style) {
copy.Value = getStyleName(copy.Value);
}
if (parameter?.ValueTypeId === VALUETYPES.Layer) {
copy.Value = getLayerName(copy.Value);
}
groupsToAdd.push(copy);
}
}
}
if (groupsToAdd.length > 0) {
const handsontableInstance = hotTableObjectStyleParameterRef.current?.hotInstance;
if (!handsontableInstance) return;
let currentTableData = handsontableInstance?.getSourceData() as ObjectStyleParameter[];
//Update the data in Chunks to show progress
const chunkSize = groupsToAdd.length > 5000 ? 250 : 100;
const totalChunks = Math.ceil(groupsToAdd.length / chunkSize);
// Process chunks with debounced updates
for (let chunkIndex = 0; chunkIndex < totalChunks; chunkIndex++) {
const startIdx = chunkIndex * chunkSize;
const endIdx = Math.min((chunkIndex + 1) * chunkSize, groupsToAdd.length);
const chunk = groupsToAdd.slice(startIdx, endIdx);
// Add chunk to currentTableData
currentTableData = [...currentTableData, ...chunk];
// Update progress
const progress = ((chunkIndex + 1) / totalChunks) * 100;
setProgress(progress);
// Throttle updates to prevent UI blocking
if (chunkIndex % 4 === 0 || chunkIndex === totalChunks - 1) {
await new Promise((resolve) => setTimeout(resolve, 0));
// Create a new array reference to ensure HandsOnTable detects the change
const updatedData = JSON.parse(JSON.stringify(currentTableData));
// Update only the new rows to minimize rendering
handsontableInstance.updateSettings({
data: updatedData,
});
// Force render the newly added rows
const lastVisibleRow = handsontableInstance.countRenderedRows();
if (lastVisibleRow < currentTableData.length) {
handsontableInstance.scrollViewportTo(lastVisibleRow);
}
}
}
// Final update to ensure all data is rendered
handsontableInstance.updateSettings({
data: JSON.parse(JSON.stringify(currentTableData)),
});
}
handleImportCloseOption();
CheckboxStateManager.toggleAll(false, []);
setIsImporting(false);
setChangesMade(true);
};
This is the portion of the code where I try to import data where it gets data from two models one from ObjectStyleParameter and from ObjectStyles but when we import the handsontable it only renders the data for ObjectStyleParameter without any issues but the ObjectStyleParameter.Value data does not render. The issue happens we have significantly large data like more than 1000 records. I have tried using just updateData, loadData but to no avail. What can I do?