Grid selection
This commit is contained in:
@@ -1,3 +1,10 @@
|
||||
import {
|
||||
IconEdit,
|
||||
IconExclamationMark,
|
||||
IconRefresh,
|
||||
IconSquarePlus,
|
||||
IconTrashX,
|
||||
} from '@tabler/icons-react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
|
||||
import type { MantineBetterMenuInstanceItem } from '../../MantineBetterMenu';
|
||||
@@ -7,9 +14,14 @@ import type { GridlerColumn } from './Column';
|
||||
import { type GridlerProps, type GridlerState, useGridlerStore } from './Store';
|
||||
|
||||
export function GlidlerFormInterface(props: {
|
||||
descriptionField?: ((data: Record<string, unknown>) => string) | string;
|
||||
getMenuItems?: GridlerProps['getMenuItems'];
|
||||
onReload?: () => void;
|
||||
onRequestForm: (request: FormRequestType, data: Record<string, unknown>) => void;
|
||||
onRequestForm: (
|
||||
request: FormRequestType,
|
||||
data: Array<Record<string, unknown>> | Record<string, unknown>
|
||||
) => void;
|
||||
showDescriptionInMenu?: boolean;
|
||||
}) {
|
||||
const [getState, mounted, setState, reload] = useGridlerStore((s) => [
|
||||
s.getState,
|
||||
@@ -22,7 +34,7 @@ export function GlidlerFormInterface(props: {
|
||||
(
|
||||
id: string,
|
||||
storeState: GridlerState,
|
||||
row?: unknown,
|
||||
row?: Record<string, unknown>,
|
||||
col?: GridlerColumn,
|
||||
defaultItems?: Array<unknown>
|
||||
) => {
|
||||
@@ -33,13 +45,26 @@ export function GlidlerFormInterface(props: {
|
||||
}
|
||||
|
||||
const items = [] as Array<MantineBetterMenuInstanceItem>;
|
||||
if (defaultItems && id === 'cell') {
|
||||
items.push(...(defaultItems as Array<MantineBetterMenuInstanceItem>));
|
||||
}
|
||||
const rows = getState('_gridSelection')?.rows.toArray() ?? [];
|
||||
const manyRows = rows.length > 1;
|
||||
|
||||
if (!row) {
|
||||
const firstRow = getState('_gridSelection')?.rows?.first();
|
||||
const firstRow = rows[0];
|
||||
if (firstRow !== undefined) {
|
||||
row = storeState.getRowBuffer(firstRow);
|
||||
}
|
||||
}
|
||||
|
||||
const desc =
|
||||
typeof props.descriptionField === 'string'
|
||||
? row?.[props.descriptionField]
|
||||
: typeof props.descriptionField === 'function' && row
|
||||
? props.descriptionField(row)
|
||||
: undefined;
|
||||
|
||||
if (id === 'other') {
|
||||
items.push({
|
||||
c: 'blue',
|
||||
@@ -51,35 +76,70 @@ export function GlidlerFormInterface(props: {
|
||||
}
|
||||
if ((id === 'cell' && row) || (id === 'menu' && row)) {
|
||||
items.push({
|
||||
c: 'blue',
|
||||
c: 'teal',
|
||||
label: 'Add',
|
||||
leftSection: <IconSquarePlus color="teal" size={16} />,
|
||||
onClick: () => {
|
||||
props.onRequestForm('insert', row as Record<string, unknown>);
|
||||
},
|
||||
});
|
||||
if (!manyRows) {
|
||||
items.push({
|
||||
c: 'green',
|
||||
label: `Modify${desc && props.showDescriptionInMenu ? ` (${desc})` : ''}`,
|
||||
leftSection: <IconEdit color="green" size={16} />,
|
||||
onClick: () => {
|
||||
props.onRequestForm('change', row as Record<string, unknown>);
|
||||
},
|
||||
});
|
||||
items.push({
|
||||
c: 'red',
|
||||
label: `Remove${desc && props.showDescriptionInMenu ? ` (${desc})` : ''}`,
|
||||
leftSection: <IconTrashX color="maroon" size={16} />,
|
||||
onClick: () => {
|
||||
props.onRequestForm('delete', row as Record<string, unknown>);
|
||||
},
|
||||
});
|
||||
} else {
|
||||
items.push({
|
||||
c: 'green',
|
||||
label: `Modify All Selected (${rows.length})`,
|
||||
leftSection: <IconEdit color="green" size={16} />,
|
||||
onClick: () => {
|
||||
props.onRequestForm(
|
||||
'change',
|
||||
rows.map((r) => storeState.getRowBuffer(r)) as Array<Record<string, unknown>>
|
||||
);
|
||||
},
|
||||
});
|
||||
items.push({
|
||||
c: 'red',
|
||||
label: `Remove All Selected (${rows.length})`,
|
||||
leftSection: <IconTrashX color="maroon" size={16} />,
|
||||
onClick: () => {
|
||||
props.onRequestForm(
|
||||
'delete',
|
||||
rows.map((r) => storeState.getRowBuffer(r)) as Array<Record<string, unknown>>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
items.push({
|
||||
c: 'green',
|
||||
label: 'Change',
|
||||
onClick: () => {
|
||||
props.onRequestForm('change', row as Record<string, unknown>);
|
||||
},
|
||||
isDivider: true,
|
||||
});
|
||||
} else if ((id === 'cell' && !row) || (id === 'menu' && !row)) {
|
||||
items.push({
|
||||
c: 'red',
|
||||
label: 'Delete',
|
||||
onClick: () => {
|
||||
props.onRequestForm('delete', row as Record<string, unknown>);
|
||||
},
|
||||
label: `Nothing Selected`,
|
||||
leftSection: <IconExclamationMark color="yellow" size={16} />,
|
||||
});
|
||||
}
|
||||
|
||||
items.push({
|
||||
isDivider: true,
|
||||
});
|
||||
|
||||
items.push({
|
||||
c: 'orange',
|
||||
label: 'Refresh',
|
||||
leftSection: <IconRefresh color="orange" size={16} />,
|
||||
onClick: () => {
|
||||
reload?.();
|
||||
},
|
||||
|
||||
@@ -32,6 +32,7 @@ import { ColumnFilterSet, type GridlerColumn, type GridlerColumns } from './Colu
|
||||
import { SortDownSprite } from './sprites/SortDown';
|
||||
import { SortUpSprite } from './sprites/SortUp';
|
||||
import { SpriteImage } from './sprites/SpriteImage';
|
||||
import { IconGrid4x4 } from '@tabler/icons-react';
|
||||
|
||||
export type FilterOption = {
|
||||
datatype?: 'array' | 'boolean' | 'date' | 'function' | 'number' | 'object' | 'string';
|
||||
@@ -418,14 +419,65 @@ const { Provider, useStore: useGridlerStore } = createSyncStore<GridlerStoreStat
|
||||
: coldef
|
||||
? [
|
||||
{
|
||||
label: `Column ${coldef?.title ?? coldef?.id} Row ${row}`,
|
||||
items: [
|
||||
{
|
||||
label: 'Sort Ascending',
|
||||
leftSection: <SpriteImage sprite={SortUpSprite} />,
|
||||
onClick: () => {
|
||||
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: () => {
|
||||
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;
|
||||
});
|
||||
},
|
||||
},
|
||||
{
|
||||
label: `Filter ${coldef?.title ?? coldef?.id}`,
|
||||
},
|
||||
{
|
||||
renderer: <ColumnFilterSet column={coldef} storeState={get()} />,
|
||||
},
|
||||
],
|
||||
label: `Column Settings for ${coldef?.title ?? coldef?.id}`,
|
||||
leftSection: <IconGrid4x4 size={16} />,
|
||||
},
|
||||
]
|
||||
: [
|
||||
{
|
||||
label: `No Column ${area}`,
|
||||
},
|
||||
];
|
||||
: [];
|
||||
s.hideMenu?.(area);
|
||||
|
||||
s.showMenu?.(area, {
|
||||
|
||||
@@ -94,6 +94,7 @@ export const GridlerGoAPIExampleEventlog = () => {
|
||||
>
|
||||
<Gridler.APIAdaptorGoLangv2 authtoken={apiKey} url={`${apiUrl}/public/process`} />
|
||||
<Gridler.GlidlerFormInterface
|
||||
descriptionField={'process'}
|
||||
onRequestForm={(request, data) => {
|
||||
console.log('Form requested', request, data);
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user