import merge from 'lodash/merge'; import get from 'lodash/get'; import React, { ComponentType, Dispatch, Fragment, ReducerAction, useMemo, useState, useEffect, useCallback } from 'react'; import { JsonFormsDispatch, JsonFormsStateContext, withJsonFormsContext } from '@json-forms/react'; import { composePaths, ControlElement, findUISchema, JsonFormsRendererRegistryEntry, JsonSchema, moveDown, moveUp, Resolve, update, JsonFormsCellRendererRegistryEntry, JsonFormsUISchemaRegistryEntry, getFirstPrimitiveProp, createId, removeId } from '@json-forms/core'; import IconButton from '@material-ui/core/IconButton'; import Accordion from '@material-ui/core/Accordion'; import AccordionSummary from '@material-ui/core/AccordionSummary'; import AccordionDetails from '@material-ui/core/AccordionDetails'; import { Grid } from '@material-ui/core'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import Avatar from '@material-ui/core/Avatar'; import DeleteIcon from '@material-ui/icons/Delete'; import ArrowUpward from '@material-ui/icons/ArrowUpward'; import ArrowDownward from '@material-ui/icons/ArrowDownward'; const iconStyle: any = { float: 'right' }; interface OwnPropsOfExpandPanel { index: number; path: string; uischema: ControlElement; schema: JsonSchema; expanded: boolean; renderers?: JsonFormsRendererRegistryEntry[]; cells?: JsonFormsCellRendererRegistryEntry[]; uischemas?: JsonFormsUISchemaRegistryEntry[]; rootSchema: JsonSchema; enableMoveUp: boolean; enableMoveDown: boolean; config: any; childLabelProp?: string; handleExpansion(panel: string): (event: any, expanded: boolean) => void; } interface StatePropsOfExpandPanel extends OwnPropsOfExpandPanel { childLabel: string; childPath: string; enableMoveUp: boolean; enableMoveDown: boolean; } /** * Dispatch props of a table control */ export interface DispatchPropsOfExpandPanel { removeItems(path: string, toDelete: number[]): (event: any) => void; moveUp(path: string, toMove: number): (event: any) => void; moveDown(path: string, toMove: number): (event: any) => void; } export interface ExpandPanelProps extends StatePropsOfExpandPanel, DispatchPropsOfExpandPanel {} const ExpandPanelRendererComponent = (props: ExpandPanelProps) => { const [labelHtmlId] = useState(createId('expand-panel')); useEffect(() => { return () => { removeId(labelHtmlId); }; }, [labelHtmlId]); const { childLabel, childPath, index, expanded, moveDown, moveUp, enableMoveDown, enableMoveUp, handleExpansion, removeItems, path, rootSchema, schema, uischema, uischemas, renderers, cells, config } = props; const foundUISchema = useMemo( () => findUISchema( uischemas, schema, uischema.scope, path, undefined, uischema, rootSchema ), [uischemas, schema, uischema.scope, path, uischema, rootSchema] ); const appliedUiSchemaOptions = merge({}, config, uischema.options); return ( }> {index + 1} {childLabel} {appliedUiSchemaOptions.showSortButtons ? ( ) : ( '' )} ); }; const ExpandPanelRenderer = React.memo(ExpandPanelRendererComponent); /** * Maps state to dispatch properties of an expand pandel control. * * @param dispatch the store's dispatch method * @returns {DispatchPropsOfArrayControl} dispatch props of an expand panel control */ export const ctxDispatchToExpandPanelProps: ( dispatch: Dispatch> ) => DispatchPropsOfExpandPanel = dispatch => ({ removeItems: useCallback((path: string, toDelete: number[]) => (event: any): void => { event.stopPropagation(); dispatch( update(path, array => { toDelete .sort() .reverse() .forEach(s => array.splice(s, 1)); return array; }) ); }, [dispatch]), moveUp: useCallback((path: string, toMove: number) => (event: any): void => { event.stopPropagation(); dispatch( update(path, array => { moveUp(array, toMove); return array; }) ); }, [dispatch]), moveDown: useCallback((path: string, toMove: number) => (event: any): void => { event.stopPropagation(); dispatch( update(path, array => { moveDown(array, toMove); return array; }) ); }, [dispatch]) }); /** * Map state to control props. * @param state the JSON Forms state * @param ownProps any own props * @returns {StatePropsOfControl} state props for a control */ export const withContextToExpandPanelProps = ( Component: ComponentType ): ComponentType => ({ ctx, props }: JsonFormsStateContext & ExpandPanelProps) => { const dispatchProps = ctxDispatchToExpandPanelProps(ctx.dispatch); const { childLabelProp, schema, path, index, uischemas } = props; const childPath = composePaths(path, `${index}`); const childData = Resolve.data(ctx.core.data, childPath); const childLabel = childLabelProp ? get(childData, childLabelProp, '') : get(childData, getFirstPrimitiveProp(schema), ''); return ( ); }; export const withJsonFormsExpandPanelProps = ( Component: ComponentType ): ComponentType => withJsonFormsContext( withContextToExpandPanelProps(Component)); export default withJsonFormsExpandPanelProps(ExpandPanelRenderer);