oranguru/src/Gridler/components/Computer.tsx

248 lines
6.1 KiB
TypeScript

/* eslint-disable react-hooks/exhaustive-deps */
import { CompactSelection } from '@glideapps/glide-data-grid';
import React, { useEffect, useRef } from 'react';
import { useGridlerStore } from './Store';
//The computer component does not need to be recalculated on every render, so we use React.memo to prevent unnecessary re-renders.
export const Computer = React.memo(() => {
const refFirstRun = useRef(0);
const refLastFilters = useRef<any>(null);
const {
_glideref,
_gridSelectionRows,
askAPIRowNumber,
colFilters,
colOrder,
colSize,
colSort,
columns,
getState,
loadPage,
setState,
setStateFN,
values,
} = useGridlerStore((s) => ({
_glideref: s._glideref,
_gridSelectionRows: s._gridSelectionRows,
askAPIRowNumber: s.askAPIRowNumber,
colFilters: s.colFilters,
colOrder: s.colOrder,
colSize: s.colSize,
colSort: s.colSort,
columns: s.columns,
getState: s.getState,
loadPage: s.loadPage,
setState: s.setState,
setStateFN: s.setStateFN,
uniqueid: s.uniqueid,
values: s.values,
}));
useEffect(() => {
const searchSelection = async () => {
const page_data = getState('_page_data');
const pageSize = getState('pageSize');
const keyField = getState('keyField') ?? 'id';
const rowIndexes = [];
for (const vi in values as Array<any>) {
let rowIndex = -1;
const key = String(
typeof values?.[vi] === 'object'
? values?.[vi]?.[keyField]
: typeof values?.[vi] === 'string'
? values?.[vi]
: undefined
);
for (const p in page_data) {
for (const r in page_data[p]) {
const idx = Number(p) * pageSize + Number(r);
if (String(page_data[p][r]?.[keyField]) === key) {
//console.log('Found row S', idx, page_data[p][r], page_data[p][r]?.[keyField], key);
rowIndex = idx;
break;
}
}
if (rowIndex >= 0) {
rowIndexes.push(rowIndex);
break;
}
}
if (!(rowIndex >= 0) && typeof askAPIRowNumber === 'function') {
const idx = await askAPIRowNumber(key);
if (idx) {
rowIndexes.push(idx);
}
}
}
return rowIndexes;
};
if (values) {
searchSelection().then((rowIndexes) => {
let rows = CompactSelection.empty();
rowIndexes.forEach((r) => {
rows = rows.add(r);
});
setStateFN('_gridSelectionRows', () => {
return rows;
});
setStateFN('_gridSelection', (c) => ({
columns: c?.columns ?? CompactSelection.empty(),
...c,
rows,
}));
});
}
}, [values]);
useEffect(() => {
const onChange = getState('onChange');
if (onChange && typeof onChange === 'function') {
const page_data = getState('_page_data');
const pageSize = getState('pageSize');
const buffers = [];
if (_gridSelectionRows) {
for (const range of _gridSelectionRows) {
let buffer = undefined;
for (const p in page_data) {
for (const r in page_data[p]) {
const idx = Number(p) * pageSize + Number(r);
if (isNaN(idx)) {
continue;
}
if (Number(page_data[p][r]?._rownumber) === range + 1) {
buffer = page_data[p][r];
//console.log('Found row', range, idx, page_data[p][r]?._rownumber);
break;
} else if (idx === range + 1) {
buffer = page_data[p][r];
//console.log('Found row 2', range, idx, page_data[p][r]?._rownumber);
break;
}
}
}
if (buffer !== undefined) {
buffers.push(buffer);
}
}
}
const _values = getState('values');
if (JSON.stringify(_values) !== JSON.stringify(buffers)) {
onChange(buffers);
}
}
}, [JSON.stringify(_gridSelectionRows), getState]);
useEffect(() => {
setState(
'renderColumns',
columns?.map((c) => ({
...c,
hasMenu: c?.hasMenu ?? true,
icon: 'sort',
}))
);
}, [columns]);
useEffect(() => {
if (!colSort) {
return;
}
setState('_gridSelection', {
columns: CompactSelection.empty(),
current: undefined,
rows: CompactSelection.empty(),
});
setState('_gridSelectionRows', CompactSelection.empty());
setStateFN('renderColumns', (cols) => {
return cols?.map((c) => ({
...c,
icon:
c.id && colSort?.find((col) => col.id === c.id)?.direction
? colSort?.find((col) => col.id === c.id)?.direction === 'asc'
? 'sortup'
: 'sortdown'
: (c.defaultIcon ?? 'sort'),
}));
}).then(() => {
loadPage(0, 'all');
});
}, [colSort]);
useEffect(() => {
if (!colFilters) {
return;
}
if (JSON.stringify(refLastFilters.current) !== JSON.stringify(colFilters)) {
loadPage(0, 'all');
refLastFilters.current = colFilters;
}
}, [colFilters]);
useEffect(() => {
if (!colSize) {
return;
}
setStateFN('renderColumns', (cols) => {
return cols?.map((c) => ({
...c,
width: c.id && colSize?.[c.id] ? colSize?.[c.id] : c.width,
}));
});
}, [colSize]);
useEffect(() => {
if (!colOrder) {
return;
}
setStateFN('renderColumns', (cols) => {
const result = cols?.sort((a, b) => {
if (colOrder[a.id] > colOrder[b.id]) {
return 1;
}
return -1;
});
return result;
});
}, [colOrder]);
useEffect(() => {
if (!_glideref) {
return;
}
if (refFirstRun.current > 0) {
return;
}
refFirstRun.current = 1;
loadPage(0);
}, [_glideref]);
// console.log('Gridler:Debug:Computer', {
// colFilters,
// colOrder,
// colSize,
// colSort,
// columns,
// uniqueid
// });
return <></>;
});