248 lines
6.1 KiB
TypeScript
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 <></>;
|
|
});
|