Work on grid
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
import { APIOptions } from '../../utils/types';
|
||||
import { useStore } from './Store';
|
||||
import type { APIOptions } from '../utils/types';
|
||||
|
||||
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 APIAdaptorGoLangv2 = React.memo((props: APIOptions) => {
|
||||
const [setStateFN, setState, getState, addError, mounted] = useStore((s) => [
|
||||
const [setStateFN, setState, getState, addError, mounted] = useGridlerStore((s) => [
|
||||
s.setStateFN,
|
||||
s.setState,
|
||||
s.getState,
|
||||
@@ -16,13 +17,14 @@ export const APIAdaptorGoLangv2 = React.memo((props: APIOptions) => {
|
||||
const useAPIQuery: (index: number) => Promise<any> = async (index: number) => {
|
||||
const colSort = getState('colSort');
|
||||
const pageSize = getState('pageSize');
|
||||
const colFilters = getState('colFilters');
|
||||
const _active_requests = getState('_active_requests');
|
||||
|
||||
if (props && props.url) {
|
||||
const head = new Headers();
|
||||
head.set('x-limit', String(pageSize ?? 50));
|
||||
head.set('x-offset', String((pageSize ?? 50) * index));
|
||||
head.set('x-fieldfilter-tablename', 'scriptcode');
|
||||
|
||||
head.set('Authorization', `Token ${props.authtoken}`);
|
||||
|
||||
if (colSort?.length && colSort.length > 0) {
|
||||
@@ -34,6 +36,14 @@ export const APIAdaptorGoLangv2 = React.memo((props: APIOptions) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (colFilters?.length && colFilters.length > 0) {
|
||||
colFilters?.filter((f)=>f.value?.length > 0)?.forEach((filter: any) => {
|
||||
if (filter.value && filter.value !== '') {
|
||||
head.set(`x-searchop-${filter.operator}-${filter.id}`, `${filter.value}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const currentRequestIndex = _active_requests?.findIndex((f) => f.page === index) ?? -1;
|
||||
_active_requests?.forEach((r) => {
|
||||
if ((r.page >= 0 && r.page < index - 2) || (index >= 0 && r.page > index + 2)) {
|
||||
@@ -80,7 +90,7 @@ export const APIAdaptorGoLangv2 = React.memo((props: APIOptions) => {
|
||||
|
||||
useEffect(() => {
|
||||
setState('useAPIQuery', useAPIQuery);
|
||||
}, [props.url, props.authtoken, mounted]);
|
||||
}, [props.url, props.authtoken, mounted, setState]);
|
||||
|
||||
return <></>;
|
||||
});
|
||||
|
||||
@@ -84,9 +84,10 @@ export const ColumnFilterInput = (props: ColumnFilterSetProps) => {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return filters;
|
||||
});
|
||||
}, [defferedFilterValue]);
|
||||
}, [defferedFilterValue, props.column.id, props.options, props.storeState]);
|
||||
|
||||
return (
|
||||
<TextInput
|
||||
@@ -128,16 +129,18 @@ export const ColumnFilterInputOperator = (props: ColumnFilterSetProps) => {
|
||||
};
|
||||
} else {
|
||||
filters.push({
|
||||
operator: 'contains',
|
||||
...props.options,
|
||||
id: props.column.id,
|
||||
value: defferedFilterValue,
|
||||
operator: defferedFilterValue,
|
||||
value: '',
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
return filters;
|
||||
});
|
||||
}, [defferedFilterValue]);
|
||||
}, [defferedFilterValue, props.column.id, props.options, props.storeState]);
|
||||
|
||||
return (
|
||||
<Select
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
|
||||
import { useStore } from './Store';
|
||||
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,
|
||||
|
||||
colFilters,
|
||||
colOrder,
|
||||
colSize,
|
||||
colSort,
|
||||
@@ -15,7 +16,7 @@ export const Computer = React.memo(() => {
|
||||
loadPage,
|
||||
setState,
|
||||
setStateFN,
|
||||
} = useStore((s) => ({
|
||||
} = useGridlerStore((s) => ({
|
||||
_glideref: s._glideref,
|
||||
colFilters: s.colFilters,
|
||||
colOrder: s.colOrder,
|
||||
@@ -59,6 +60,17 @@ export const Computer = React.memo(() => {
|
||||
});
|
||||
}, [colSort]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!colFilters) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (JSON.stringify(refLastFilters.current) !== JSON.stringify(colFilters)) {
|
||||
loadPage(0, 'all');
|
||||
refLastFilters.current = colFilters;
|
||||
}
|
||||
}, [colFilters]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!colSize) {
|
||||
return;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
import { range } from '../utils/range';
|
||||
import { useStore } from './Store';
|
||||
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 Pager = React.memo(() => {
|
||||
@@ -15,7 +15,7 @@ export const Pager = React.memo(() => {
|
||||
loadPage,
|
||||
_loadingList,
|
||||
hasLocalData
|
||||
] = useStore((s) => [
|
||||
] = useGridlerStore((s) => [
|
||||
s.setState,
|
||||
s._glideref,
|
||||
s._visiblePages,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import {
|
||||
type CellArray,
|
||||
CompactSelection,
|
||||
type DataEditorProps,
|
||||
type DataEditorRef,
|
||||
type EditableGridCell,
|
||||
type GetCellsThunk,
|
||||
@@ -11,7 +12,7 @@ import {
|
||||
type GridColumn,
|
||||
type HeaderClickedEventArgs,
|
||||
type Item,
|
||||
type Rectangle,
|
||||
type Rectangle
|
||||
} from '@glideapps/glide-data-grid';
|
||||
import { getUUID } from '@warkypublic/artemis-kit';
|
||||
import { getNestedValue } from '@warkypublic/artemis-kit/object';
|
||||
@@ -57,8 +58,9 @@ export interface GridlerProps extends PropsWithChildren {
|
||||
col?: GridlerColumn,
|
||||
defaultItems?: Array<any>
|
||||
) => Array<any>;
|
||||
headerHeight?: number;
|
||||
glideProps?: Partial<DataEditorProps>
|
||||
|
||||
headerHeight?: number;
|
||||
hideMenu?: (id: string) => void;
|
||||
maxConcurrency?: number;
|
||||
pageSize?: number;
|
||||
@@ -72,6 +74,7 @@ export interface GridlerProps extends PropsWithChildren {
|
||||
) => GridCell;
|
||||
request?: TRequest;
|
||||
rowHeight?: number;
|
||||
selectedRow?: number;
|
||||
showMenu?: (id: string, options?: Partial<MantineBetterMenuInstance>) => void;
|
||||
uniqueid: string;
|
||||
}
|
||||
@@ -90,6 +93,7 @@ export interface GridlerState {
|
||||
colSize?: Record<string, number>;
|
||||
colSort?: Array<SortOption>;
|
||||
data?: Array<any>;
|
||||
|
||||
|
||||
errors: Array<string>;
|
||||
focused?: boolean;
|
||||
@@ -148,7 +152,7 @@ export type GridlerStoreState = GridlerProps & GridlerState;
|
||||
|
||||
export type SortOption = { direction: 'asc' | 'desc'; id: string; order?: number };
|
||||
|
||||
const { Provider, useStore } = createSyncStore<GridlerStoreState, GridlerProps>(
|
||||
const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreState, GridlerProps>(
|
||||
(set, get) => ({
|
||||
_loadingList: CompactSelection.empty(),
|
||||
_page_data: {},
|
||||
@@ -241,7 +245,7 @@ const { Provider, useStore } = createSyncStore<GridlerStoreState, GridlerProps>(
|
||||
loadPage: async (pPage: number, clearMode?: 'all' | 'page') => {
|
||||
const state = get();
|
||||
const page = pPage < 0 ? 0 : pPage;
|
||||
|
||||
|
||||
const damageList: { cell: [number, number] }[] = [];
|
||||
const colLen = Object.keys(state.renderColumns ?? [1, 2, 3]).length;
|
||||
const upperPage = state.pageSize * page;
|
||||
@@ -303,10 +307,11 @@ const { Provider, useStore } = createSyncStore<GridlerStoreState, GridlerProps>(
|
||||
}
|
||||
|
||||
s.setStateFN('colOrder', (cols) => {
|
||||
const renderCols = cols ?? s.renderColumns
|
||||
const renderCols =
|
||||
cols ??
|
||||
s.renderColumns
|
||||
?.map((col, i) => [col.id, i])
|
||||
.reduce((acc, [id, i]) => ({ ...acc, [id]: i }), {});;
|
||||
|
||||
.reduce((acc, [id, i]) => ({ ...acc, [id]: i }), {});
|
||||
|
||||
if (!fromItem?.id || !toItem?.id) {
|
||||
return renderCols;
|
||||
@@ -424,7 +429,8 @@ const { Provider, useStore } = createSyncStore<GridlerStoreState, GridlerProps>(
|
||||
if (!coldef) {
|
||||
return;
|
||||
}
|
||||
const items = [
|
||||
|
||||
const sortItems = [
|
||||
{
|
||||
label: `Sort ${coldef?.title ?? coldef?.id}`,
|
||||
},
|
||||
@@ -432,19 +438,46 @@ const { Provider, useStore } = createSyncStore<GridlerStoreState, GridlerProps>(
|
||||
label: 'Sort Ascending',
|
||||
leftSection: <SpriteImage sprite={SortUpSprite} />,
|
||||
onClick: () => {
|
||||
console.log('Sort Ascending');
|
||||
s.setStateFN('colSort', (c) => {
|
||||
const cols = [...(c ?? [])];
|
||||
const idx = cols.findIndex((search) => search.id === coldef.id);
|
||||
const dir = 'asc';
|
||||
if (idx < 0) {
|
||||
const newSort: SortOption = { direction: dir, id: coldef.id, order: cols?.length };
|
||||
cols.push(newSort);
|
||||
} else if (idx >= 0) {
|
||||
cols[idx].direction = dir;
|
||||
}
|
||||
|
||||
return cols;
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Sort Descending',
|
||||
leftSection: <SpriteImage sprite={SortDownSprite} />,
|
||||
onClick: () => {
|
||||
console.log('Sort Descending');
|
||||
s.setStateFN('colSort', (c) => {
|
||||
const cols = [...(c ?? [])];
|
||||
const idx = cols.findIndex((search) => search.id === coldef.id);
|
||||
const dir = 'desc';
|
||||
if (idx < 0) {
|
||||
const newSort: SortOption = { direction: dir, id: coldef.id, order: cols?.length };
|
||||
cols.push(newSort);
|
||||
} else if (idx >= 0) {
|
||||
cols[idx].direction = dir;
|
||||
}
|
||||
|
||||
return cols;
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
isDivider: true,
|
||||
},
|
||||
];
|
||||
const items = [
|
||||
...(coldef.disableSort ? []: sortItems),
|
||||
{
|
||||
label: `Filter ${coldef?.title ?? coldef?.id}`,
|
||||
},
|
||||
@@ -638,6 +671,6 @@ const { Provider, useStore } = createSyncStore<GridlerStoreState, GridlerProps>(
|
||||
}
|
||||
);
|
||||
|
||||
export type useStoreReturnType = ReturnType<typeof useStore>;
|
||||
export type useStoreReturnType = ReturnType<typeof useGridlerStore>;
|
||||
|
||||
export { Provider, useStore };
|
||||
export { Provider, useGridlerStore };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Sprite, SpriteProps } from '@glideapps/glide-data-grid';
|
||||
import type { Sprite, SpriteProps } from '@glideapps/glide-data-grid';
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Sprite, SpriteProps } from '@glideapps/glide-data-grid';
|
||||
import type { Sprite, SpriteProps } from '@glideapps/glide-data-grid';
|
||||
|
||||
export const SortDownSprite: Sprite = (props: Partial<SpriteProps>) => {
|
||||
const fg = props.fgColor ?? 'currentColor';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Sprite, SpriteProps } from '@glideapps/glide-data-grid';
|
||||
import type { Sprite, SpriteProps } from '@glideapps/glide-data-grid';
|
||||
|
||||
export const SortUpSprite: Sprite = (props: Partial<SpriteProps>) => {
|
||||
const fg = props.fgColor ?? 'currentColor';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Sprite, SpriteProps } from '@glideapps/glide-data-grid';
|
||||
import type { Sprite, SpriteProps } from '@glideapps/glide-data-grid';
|
||||
|
||||
export const SpriteImage = (props: { alt?:string; sprite: Sprite, } & Partial<SpriteProps>) => {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user