197 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			197 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import {
 | |
|   IconEdit,
 | |
|   IconExclamationMark,
 | |
|   IconRefresh,
 | |
|   IconSquarePlus,
 | |
|   IconTrashX,
 | |
| } from '@tabler/icons-react';
 | |
| import { useCallback, useEffect } from 'react';
 | |
| 
 | |
| import type { MantineBetterMenuInstanceItem } from '../../../MantineBetterMenu';
 | |
| import type { FormRequestType } from '../../utils/types';
 | |
| import type { GridlerColumn } from '../Column';
 | |
| 
 | |
| import { type GridlerProps, type GridlerState, useGridlerStore } from '../GridlerStore';
 | |
| 
 | |
| export function GlidlerFormAdaptor(props: {
 | |
|   changeOnActiveClick?: boolean;
 | |
|   descriptionField?: ((data: Record<string, unknown>) => string) | string;
 | |
|   getMenuItems?: GridlerProps['getMenuItems'];
 | |
|   onReload?: () => void;
 | |
|   onRequestForm: (
 | |
|     request: FormRequestType,
 | |
|     data: Array<Record<string, unknown>> | Record<string, unknown>
 | |
|   ) => void;
 | |
|   showDescriptionInMenu?: boolean;
 | |
| }) {
 | |
|   const [getState, mounted, setState, _events] = useGridlerStore((s) => [
 | |
|     s.getState,
 | |
|     s.mounted,
 | |
|     s.setState,
 | |
|     s._events,
 | |
|   ]);
 | |
| 
 | |
|   useEffect(() => {
 | |
|     if (mounted && props.changeOnActiveClick) {
 | |
|       const evf = (event: CustomEvent<any>) => {
 | |
|         const { row, state } = event.detail;
 | |
|         const getRowBuffer = state.getRowBuffer as (row: number) => Record<string, unknown>;
 | |
|         if (getRowBuffer) {
 | |
|           const rowData = getRowBuffer(row);
 | |
|           if (!rowData) {
 | |
|             return;
 | |
|           }
 | |
|           props.onRequestForm('change', rowData);
 | |
|         }
 | |
|       };
 | |
|       _events?.addEventListener('onCellActivated', evf as any);
 | |
|       return () => {
 | |
|         if (evf) {
 | |
|           _events?.removeEventListener('onCellActivated', evf as any);
 | |
|         }
 | |
|       };
 | |
|     }
 | |
|   }, [props.changeOnActiveClick, mounted, _events]);
 | |
| 
 | |
|   const getMenuItems = useCallback(
 | |
|     (
 | |
|       id: string,
 | |
|       storeState: GridlerState,
 | |
|       row?: Record<string, unknown>,
 | |
|       col?: GridlerColumn,
 | |
|       defaultItems?: Array<unknown>
 | |
|     ) => {
 | |
|       //console.log('GlidlerFormInterface getMenuItems', id);
 | |
| 
 | |
|       if (id === 'header-menu') {
 | |
|         return defaultItems || [];
 | |
|       }
 | |
| 
 | |
|       const items = [] as Array<MantineBetterMenuInstanceItem>;
 | |
| 
 | |
|       items.push(...(defaultItems as Array<MantineBetterMenuInstanceItem>));
 | |
| 
 | |
|       const rows = getState('_gridSelection')?.rows.toArray() ?? [];
 | |
|       const manyRows = rows.length > 1;
 | |
| 
 | |
|       if (!row) {
 | |
|         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',
 | |
|           label: 'Add',
 | |
|           onClick: () => {
 | |
|             props.onRequestForm('insert', row as Record<string, unknown>);
 | |
|           },
 | |
|         });
 | |
|       }
 | |
|       if ((id === 'cell' && row) || (id === 'menu' && row)) {
 | |
|         items.push({
 | |
|           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({
 | |
|           isDivider: true,
 | |
|         });
 | |
|       } else if ((id === 'cell' && !row) || (id === 'menu' && !row)) {
 | |
|         items.push({
 | |
|           c: 'red',
 | |
|           label: `Nothing Selected`,
 | |
|           leftSection: <IconExclamationMark color="yellow" size={16} />,
 | |
|         });
 | |
|       }
 | |
| 
 | |
|       items.push({
 | |
|         c: 'orange',
 | |
|         label: 'Refresh',
 | |
|         leftSection: <IconRefresh color="orange" size={16} />,
 | |
|         onClickAsync: async () => {
 | |
|           const _refresh = getState('_refresh');
 | |
|           await _refresh?.();
 | |
|         },
 | |
|       });
 | |
| 
 | |
|       const result = props.getMenuItems
 | |
|         ? props.getMenuItems(id, storeState, row, col, items)
 | |
|         : items;
 | |
|       //console.log('GlidlerFormInterface getMenuItems', id, items);
 | |
| 
 | |
|       if (!items || items.length === 0) {
 | |
|         return defaultItems || [];
 | |
|       }
 | |
|       return result;
 | |
|     },
 | |
|     [props.onRequestForm, getState]
 | |
|   );
 | |
| 
 | |
|   useEffect(() => {
 | |
|     if (mounted && typeof setState === 'function') {
 | |
|       //console.log('GlidlerFormInterface setState getMenuItems1', mounted);
 | |
|       if (getState('getMenuItems') !== getMenuItems) {
 | |
|         setState('getMenuItems', getMenuItems);
 | |
|       }
 | |
|     }
 | |
|     return () => {};
 | |
|   }, [props.getMenuItems, mounted]);
 | |
| 
 | |
|   return <></>;
 | |
| }
 |