Work on grid

This commit is contained in:
Hein 2025-09-22 14:58:25 +02:00
parent 46dabed765
commit ea6b100225
15 changed files with 264 additions and 65 deletions

View File

@ -10,7 +10,7 @@ import { Pager } from './components/Pager';
import { SortSprite } from './components/sprites/Sort'; import { SortSprite } from './components/sprites/Sort';
import { SortDownSprite } from './components/sprites/SortDown'; import { SortDownSprite } from './components/sprites/SortDown';
import { SortUpSprite } from './components/sprites/SortUp'; import { SortUpSprite } from './components/sprites/SortUp';
import { useStore } from './components/Store'; import { useGridlerStore } from './components/Store';
import classes from './Gridler.module.css'; import classes from './Gridler.module.css';
import { useGridTheme } from './hooks/use-grid-theme'; import { useGridTheme } from './hooks/use-grid-theme';
@ -38,7 +38,8 @@ export const GridlerDataGrid = () => {
rowHeight, rowHeight,
setStateFN, setStateFN,
total_rows, total_rows,
} = useStore((s) => ({ glideProps,
} = useGridlerStore((s) => ({
focused: s.focused, focused: s.focused,
getCellContent: s.getCellContent, getCellContent: s.getCellContent,
getCellsForSelection: s.getCellsForSelection, getCellsForSelection: s.getCellsForSelection,
@ -57,6 +58,7 @@ export const GridlerDataGrid = () => {
rowHeight: s.rowHeight, rowHeight: s.rowHeight,
setStateFN: s.setStateFN, setStateFN: s.setStateFN,
total_rows: s.total_rows, total_rows: s.total_rows,
glideProps: s.glideProps,
})); }));
const refMerged = useMergedRef(ref, (r) => { const refMerged = useMergedRef(ref, (r) => {
@ -103,6 +105,7 @@ export const GridlerDataGrid = () => {
columns={(renderColumns as Array<GridColumn>) ?? []} columns={(renderColumns as Array<GridColumn>) ?? []}
columnSelect="none" columnSelect="none"
drawFocusRing drawFocusRing
getCellContent={getCellContent} getCellContent={getCellContent}
getCellsForSelection={getCellsForSelection} getCellsForSelection={getCellsForSelection}
getRowThemeOverride={theme.getRowThemeOverride} getRowThemeOverride={theme.getRowThemeOverride}
@ -144,7 +147,16 @@ export const GridlerDataGrid = () => {
</ActionIcon> </ActionIcon>
} }
rowHeight={rowHeight ?? 22} rowHeight={rowHeight ?? 22}
//rowMarkersCheckboxStyle='square'
//rowMarkersKind='both'
rowMarkers={{
checkboxStyle: 'square',
kind: 'both'
}}
rows={total_rows} rows={total_rows}
rowSelect="multi"
// onGridSelectionChange={(sel) => { // onGridSelectionChange={(sel) => {
// console.log("Selection",sel); // console.log("Selection",sel);
// }} // }}
@ -157,10 +169,11 @@ export const GridlerDataGrid = () => {
// width: 30 // width: 30
// }} // }}
rowSelect="multi" rowSelectionMode='auto'
spanRangeBehavior="default" spanRangeBehavior="default"
theme={theme.gridTheme} theme={theme.gridTheme}
width="100%" width="100%"
{...glideProps}
/> />
{/* <Portal> */} {/* <Portal> */}
<div id="portal" /> <div id="portal" />

134
src/Gridler/README.md Normal file
View File

@ -0,0 +1,134 @@
# Gridler
A powerful React data grid component built on top of @glideapps/glide-data-grid with enhanced features for data manipulation and visualization.
## Features
### ✅ Completed Features
#### Core Grid Functionality
- **Data Display**: Support for both local data and remote API data sources
- **Column Management**: Dynamic column configuration with customizable properties
- **Cell Rendering**: Custom cell renderers with flexible display options
- **Row Selection**: Multi-row selection capabilities
- **Context Menus**: Right-click context menus for cells, headers, and general grid areas
#### Sorting & Filtering
- **Local File Sorting**: Built-in sorting for local data sources
- **Column Sorting**: Click-to-sort headers with ascending/descending indicators
- **Advanced Filtering**: Column-based filtering with multiple operators:
- Contains, Equal, Not Equal
- Greater Than, Greater Than or Equal
- Less Than, Less Than or Equal
- Between, Starts With, Ends With
- **Filter UI**: Dedicated filter input components with debounced search
- **Searching**: Built-in search functionality across data
#### Column Features
- **Show/Hide Columns**: Dynamic column visibility control
- **Column Resizing**: Adjustable column widths with min/max constraints
- **Column Reordering**: Drag-and-drop column repositioning
- **Column Persistence**: Automatic saving of column order and sizes
- **Filtering Interface/Menu**: Comprehensive filtering controls per column
#### Data Management
- **Pagination**: Built-in pager component for large datasets
- **Progressive Scrolling**: Efficient rendering for large data sets
- **State Persistence**: Column preferences saved across sessions
- **Error Handling**: Comprehensive error management and display
#### UI/UX Features
- **Theme Support**: Customizable grid themes with dark/light mode support
- **Responsive Design**: Adaptive layout for different screen sizes
- **Loading States**: Visual feedback during data loading
- **Keyboard Navigation**: Full keyboard accessibility
- **Sprites/Icons**: Custom sort indicators and UI elements
#### Integration Features
- **API Adaptor**: Go Lang v2 REST API integration
- **Zustand Store**: Centralized state management
- **Mantine Integration**: Seamless integration with Mantine UI components
- **TypeScript Support**: Full TypeScript definitions and type safety
### 🚧 Planned Features
#### Enhanced Filtering
- **Date Range Filters**: Specialized date/time filtering controls
- **Multi-Select Filters**: Dropdown filters with multiple selection options
- **Custom Filter Types**: Support for custom filter implementations
- **Filter Presets**: Save and load common filter combinations
- **Advanced Search**: Global search with highlighting and regex support
#### Export/Import
- **CSV Export**: Export filtered/sorted data to CSV format
- **Excel Export**: Export to Excel with formatting preservation
- **JSON Export**: Export data in JSON format
- **Print Support**: Print-friendly grid layouts
- **Data Import**: Import data from various file formats
#### Advanced Grid Features
- **Cell Editing**: In-place cell editing with validation
- **Bulk Operations**: Multi-row operations (delete, update, etc.)
- **Grouping**: Row grouping with expand/collapse functionality
- **Aggregation**: Column aggregation (sum, average, count, etc.)
- **Virtual Scrolling**: Enhanced performance for very large datasets
- **Frozen Columns**: Pin important columns to left/right
- **Row Grouping**: Hierarchical data display
#### UI Enhancements
- **Column Templates**: Pre-defined column configurations
- **Grid Templates**: Save and load entire grid configurations
- **Toolbar Customization**: Configurable toolbar with custom actions
- **Status Bar**: Display grid statistics and information
- **Full Screen Mode**: Maximize grid to full viewport
- **Responsive Breakpoints**: Better mobile/tablet support
#### Performance & Optimization
- **Data Virtualization**: Improved virtual scrolling implementation
- **Lazy Loading**: On-demand data loading for large datasets
- **Caching Strategy**: Intelligent data caching for better performance
- **Memory Optimization**: Reduced memory footprint for large grids
#### Developer Experience
- **Plugin System**: Extensible plugin architecture
- **Custom Hooks**: Reusable hooks for common grid operations
- **Documentation**: Comprehensive API documentation and examples
- **Testing Suite**: Complete test coverage for all features
- **Storybook Stories**: Interactive component examples
## Usage
```tsx
import { Gridler } from './Gridler';
const MyGrid = () => {
const columns = [
{ id: 'name', title: 'Name', width: 200 },
{ id: 'email', title: 'Email', width: 250 },
{ id: 'role', title: 'Role', width: 150 }
];
const data = [
{ name: 'John Doe', email: 'john@example.com', role: 'Admin' },
{ name: 'Jane Smith', email: 'jane@example.com', role: 'User' }
];
return (
<Gridler
uniqueid="my-grid"
columns={columns}
data={data}
/>
);
};
```
## Architecture
- **Gridler.tsx**: Main component wrapper with provider setup
- **GridlerDataGrid.tsx**: Core data grid implementation
- **Store.tsx**: Zustand-based state management
- **Column.tsx**: Column definitions and filtering components
- **components/**: Reusable grid components (Pager, Computer, etc.)
- **hooks/**: Custom React hooks for grid functionality
- **utils/**: Utility functions and type definitions

View File

@ -1,11 +1,12 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { APIOptions } from '../../utils/types'; import type { APIOptions } from '../utils/types';
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. //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) => { 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.setStateFN,
s.setState, s.setState,
s.getState, s.getState,
@ -16,13 +17,14 @@ export const APIAdaptorGoLangv2 = React.memo((props: APIOptions) => {
const useAPIQuery: (index: number) => Promise<any> = async (index: number) => { const useAPIQuery: (index: number) => Promise<any> = async (index: number) => {
const colSort = getState('colSort'); const colSort = getState('colSort');
const pageSize = getState('pageSize'); const pageSize = getState('pageSize');
const colFilters = getState('colFilters');
const _active_requests = getState('_active_requests'); const _active_requests = getState('_active_requests');
if (props && props.url) { if (props && props.url) {
const head = new Headers(); const head = new Headers();
head.set('x-limit', String(pageSize ?? 50)); head.set('x-limit', String(pageSize ?? 50));
head.set('x-offset', String((pageSize ?? 50) * index)); head.set('x-offset', String((pageSize ?? 50) * index));
head.set('x-fieldfilter-tablename', 'scriptcode');
head.set('Authorization', `Token ${props.authtoken}`); head.set('Authorization', `Token ${props.authtoken}`);
if (colSort?.length && colSort.length > 0) { 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; const currentRequestIndex = _active_requests?.findIndex((f) => f.page === index) ?? -1;
_active_requests?.forEach((r) => { _active_requests?.forEach((r) => {
if ((r.page >= 0 && r.page < index - 2) || (index >= 0 && r.page > index + 2)) { 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(() => { useEffect(() => {
setState('useAPIQuery', useAPIQuery); setState('useAPIQuery', useAPIQuery);
}, [props.url, props.authtoken, mounted]); }, [props.url, props.authtoken, mounted, setState]);
return <></>; return <></>;
}); });

View File

@ -84,9 +84,10 @@ export const ColumnFilterInput = (props: ColumnFilterSetProps) => {
}); });
} }
return filters; return filters;
}); });
}, [defferedFilterValue]); }, [defferedFilterValue, props.column.id, props.options, props.storeState]);
return ( return (
<TextInput <TextInput
@ -128,16 +129,18 @@ export const ColumnFilterInputOperator = (props: ColumnFilterSetProps) => {
}; };
} else { } else {
filters.push({ filters.push({
operator: 'contains',
...props.options, ...props.options,
id: props.column.id, id: props.column.id,
value: defferedFilterValue, operator: defferedFilterValue,
value: '',
}); });
} }
return filters; return filters;
}); });
}, [defferedFilterValue]); }, [defferedFilterValue, props.column.id, props.options, props.storeState]);
return ( return (
<Select <Select

View File

@ -1,13 +1,14 @@
import React, { useEffect, useRef } from 'react'; 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. //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(() => { export const Computer = React.memo(() => {
const refFirstRun = useRef(0); const refFirstRun = useRef(0);
const refLastFilters = useRef<any>(null);
const { const {
_glideref, _glideref,
colFilters,
colOrder, colOrder,
colSize, colSize,
colSort, colSort,
@ -15,7 +16,7 @@ export const Computer = React.memo(() => {
loadPage, loadPage,
setState, setState,
setStateFN, setStateFN,
} = useStore((s) => ({ } = useGridlerStore((s) => ({
_glideref: s._glideref, _glideref: s._glideref,
colFilters: s.colFilters, colFilters: s.colFilters,
colOrder: s.colOrder, colOrder: s.colOrder,
@ -59,6 +60,17 @@ export const Computer = React.memo(() => {
}); });
}, [colSort]); }, [colSort]);
useEffect(() => {
if (!colFilters) {
return;
}
if (JSON.stringify(refLastFilters.current) !== JSON.stringify(colFilters)) {
loadPage(0, 'all');
refLastFilters.current = colFilters;
}
}, [colFilters]);
useEffect(() => { useEffect(() => {
if (!colSize) { if (!colSize) {
return; return;

View File

@ -2,7 +2,7 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import { range } from '../utils/range'; 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. //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(() => { export const Pager = React.memo(() => {
@ -15,7 +15,7 @@ export const Pager = React.memo(() => {
loadPage, loadPage,
_loadingList, _loadingList,
hasLocalData hasLocalData
] = useStore((s) => [ ] = useGridlerStore((s) => [
s.setState, s.setState,
s._glideref, s._glideref,
s._visiblePages, s._visiblePages,

View File

@ -3,6 +3,7 @@
import { import {
type CellArray, type CellArray,
CompactSelection, CompactSelection,
type DataEditorProps,
type DataEditorRef, type DataEditorRef,
type EditableGridCell, type EditableGridCell,
type GetCellsThunk, type GetCellsThunk,
@ -11,7 +12,7 @@ import {
type GridColumn, type GridColumn,
type HeaderClickedEventArgs, type HeaderClickedEventArgs,
type Item, type Item,
type Rectangle, type Rectangle
} from '@glideapps/glide-data-grid'; } from '@glideapps/glide-data-grid';
import { getUUID } from '@warkypublic/artemis-kit'; import { getUUID } from '@warkypublic/artemis-kit';
import { getNestedValue } from '@warkypublic/artemis-kit/object'; import { getNestedValue } from '@warkypublic/artemis-kit/object';
@ -57,8 +58,9 @@ export interface GridlerProps extends PropsWithChildren {
col?: GridlerColumn, col?: GridlerColumn,
defaultItems?: Array<any> defaultItems?: Array<any>
) => Array<any>; ) => Array<any>;
headerHeight?: number; glideProps?: Partial<DataEditorProps>
headerHeight?: number;
hideMenu?: (id: string) => void; hideMenu?: (id: string) => void;
maxConcurrency?: number; maxConcurrency?: number;
pageSize?: number; pageSize?: number;
@ -72,6 +74,7 @@ export interface GridlerProps extends PropsWithChildren {
) => GridCell; ) => GridCell;
request?: TRequest; request?: TRequest;
rowHeight?: number; rowHeight?: number;
selectedRow?: number;
showMenu?: (id: string, options?: Partial<MantineBetterMenuInstance>) => void; showMenu?: (id: string, options?: Partial<MantineBetterMenuInstance>) => void;
uniqueid: string; uniqueid: string;
} }
@ -90,6 +93,7 @@ export interface GridlerState {
colSize?: Record<string, number>; colSize?: Record<string, number>;
colSort?: Array<SortOption>; colSort?: Array<SortOption>;
data?: Array<any>; data?: Array<any>;
errors: Array<string>; errors: Array<string>;
focused?: boolean; focused?: boolean;
@ -148,7 +152,7 @@ export type GridlerStoreState = GridlerProps & GridlerState;
export type SortOption = { direction: 'asc' | 'desc'; id: string; order?: number }; 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) => ({ (set, get) => ({
_loadingList: CompactSelection.empty(), _loadingList: CompactSelection.empty(),
_page_data: {}, _page_data: {},
@ -241,7 +245,7 @@ const { Provider, useStore } = createSyncStore<GridlerStoreState, GridlerProps>(
loadPage: async (pPage: number, clearMode?: 'all' | 'page') => { loadPage: async (pPage: number, clearMode?: 'all' | 'page') => {
const state = get(); const state = get();
const page = pPage < 0 ? 0 : pPage; const page = pPage < 0 ? 0 : pPage;
const damageList: { cell: [number, number] }[] = []; const damageList: { cell: [number, number] }[] = [];
const colLen = Object.keys(state.renderColumns ?? [1, 2, 3]).length; const colLen = Object.keys(state.renderColumns ?? [1, 2, 3]).length;
const upperPage = state.pageSize * page; const upperPage = state.pageSize * page;
@ -303,10 +307,11 @@ const { Provider, useStore } = createSyncStore<GridlerStoreState, GridlerProps>(
} }
s.setStateFN('colOrder', (cols) => { s.setStateFN('colOrder', (cols) => {
const renderCols = cols ?? s.renderColumns const renderCols =
cols ??
s.renderColumns
?.map((col, i) => [col.id, i]) ?.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) { if (!fromItem?.id || !toItem?.id) {
return renderCols; return renderCols;
@ -424,7 +429,8 @@ const { Provider, useStore } = createSyncStore<GridlerStoreState, GridlerProps>(
if (!coldef) { if (!coldef) {
return; return;
} }
const items = [
const sortItems = [
{ {
label: `Sort ${coldef?.title ?? coldef?.id}`, label: `Sort ${coldef?.title ?? coldef?.id}`,
}, },
@ -432,19 +438,46 @@ const { Provider, useStore } = createSyncStore<GridlerStoreState, GridlerProps>(
label: 'Sort Ascending', label: 'Sort Ascending',
leftSection: <SpriteImage sprite={SortUpSprite} />, leftSection: <SpriteImage sprite={SortUpSprite} />,
onClick: () => { 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', label: 'Sort Descending',
leftSection: <SpriteImage sprite={SortDownSprite} />, leftSection: <SpriteImage sprite={SortDownSprite} />,
onClick: () => { 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, isDivider: true,
}, },
];
const items = [
...(coldef.disableSort ? []: sortItems),
{ {
label: `Filter ${coldef?.title ?? coldef?.id}`, 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 };

View File

@ -1,4 +1,4 @@
import { Sprite, SpriteProps } from '@glideapps/glide-data-grid'; import type { Sprite, SpriteProps } from '@glideapps/glide-data-grid';

View File

@ -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>) => { export const SortDownSprite: Sprite = (props: Partial<SpriteProps>) => {
const fg = props.fgColor ?? 'currentColor'; const fg = props.fgColor ?? 'currentColor';

View File

@ -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>) => { export const SortUpSprite: Sprite = (props: Partial<SpriteProps>) => {
const fg = props.fgColor ?? 'currentColor'; const fg = props.fgColor ?? 'currentColor';

View File

@ -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>) => { export const SpriteImage = (props: { alt?:string; sprite: Sprite, } & Partial<SpriteProps>) => {
return ( return (

View File

@ -3,7 +3,7 @@ import type { GetRowThemeCallback } from '@glideapps/glide-data-grid';
import { darken, lighten, useMantineColorScheme, useMantineTheme } from '@mantine/core'; import { darken, lighten, useMantineColorScheme, useMantineTheme } from '@mantine/core';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import { useStore } from '../components/Store'; import { useGridlerStore } from '../components/Store';
export const offsetRows = (colorScheme: any) => (i: number) => export const offsetRows = (colorScheme: any) => (i: number) =>
i % 2 === 0 i % 2 === 0
@ -15,7 +15,7 @@ export const offsetRows = (colorScheme: any) => (i: number) =>
export const useGridTheme = () => { export const useGridTheme = () => {
const theme = useMantineTheme(); const theme = useMantineTheme();
const { colorScheme } = useMantineColorScheme(); const { colorScheme } = useMantineColorScheme();
const { enableOddEvenRowColor, focused } = useStore((state) => ({ const { enableOddEvenRowColor, focused } = useGridlerStore((state) => ({
enableOddEvenRowColor: state.enableOddEvenRowColor, enableOddEvenRowColor: state.enableOddEvenRowColor,
focused: state.focused focused: state.focused
})); }));

3
src/Gridler/index.ts Normal file
View File

@ -0,0 +1,3 @@
export * from './components/Column'
export {useGridlerStore } from './components/Store'
export {Gridler} from './Gridler'

View File

@ -15,37 +15,25 @@ export const GridlerGoAPIExampleEventlog = () => {
const columns: GridlerColumns = [ const columns: GridlerColumns = [
{ {
id: 'rid_atevent', id: 'id_process',
title: 'RID', title: 'RID',
width: 100, width: 100,
}, },
{ {
Cell: (_row, _col, _colindex, value) => { id: 'process',
return { title: 'Process',
cursor: 'crosshair',
data: value,
displayData: `- ${value}`,
kind: 'text',
};
},
grow: 1,
id: 'changedate',
title: 'Date',
width: 200, width: 200,
}, },
{ {
id: 'changetime', id: 'processtype',
title: 'Time', title: 'Type',
width: 200,
},
{
id: 'changeuser',
title: 'User',
}, },
{ {
id: 'actionx', disableSort: true,
title: 'Action', id: 'status',
title: 'Status',
width: 100, width: 100,
}, },
]; ];
@ -61,18 +49,18 @@ export const GridlerGoAPIExampleEventlog = () => {
getMenuItems={(id, _state, row, col, defaultItems) => { getMenuItems={(id, _state, row, col, defaultItems) => {
return [ return [
...(defaultItems ?? []), ...(defaultItems ?? []),
{ // {
id: 'test', // id: 'test',
label: `Test ${id}`, // label: `Test -${id}`,
onClick: () => { // onClick: () => {
console.log('Test clicked', row, col); // console.log('Test clicked', row, col);
}, // },
}, // },
]; ];
}} }}
uniqueid="gridtest" uniqueid="gridtest"
> >
<APIAdaptorGoLangv2 authtoken={apiKey} url={`${apiUrl}/core/atevent`} /> <APIAdaptorGoLangv2 authtoken={apiKey} url={`${apiUrl}/public/process`} />
</Gridler> </Gridler>
</Stack> </Stack>
); );

View File

@ -1,7 +1,10 @@
export * from './Gridler'
export { export {
type MantineBetterMenuInstance, type MantineBetterMenuInstance,
type MantineBetterMenuInstanceItem, type MantineBetterMenuInstanceItem,
MantineBetterMenusProvider, MantineBetterMenusProvider,
type MenuStoreState, type MenuStoreState,
useMantineBetterMenus, useMantineBetterMenus,
} from "./MantineBetterMenu"; } from "./MantineBetterMenu";