diff --git a/src/components/dataDisplays/HoustonSightingsDisplay.jsx b/src/components/dataDisplays/HoustonSightingsDisplay.jsx index 29bccf5f..06a67cb5 100644 --- a/src/components/dataDisplays/HoustonSightingsDisplay.jsx +++ b/src/components/dataDisplays/HoustonSightingsDisplay.jsx @@ -1,7 +1,7 @@ import React from 'react'; import ActionIcon from '../ActionIcon'; -import { cellRendererTypes } from '../dataDisplays/cellRenderers'; +import { cellRendererTypes } from './cellRenderers'; import DataDisplay from './DataDisplay'; export default function HoustonSightingsDisplay({ diff --git a/src/components/dataDisplays/cellRenderers/ActionGroupRenderer.jsx b/src/components/dataDisplays/cellRenderers/ActionGroupRenderer.jsx new file mode 100644 index 00000000..fdb52f94 --- /dev/null +++ b/src/components/dataDisplays/cellRenderers/ActionGroupRenderer.jsx @@ -0,0 +1,95 @@ +import React, { useMemo } from 'react'; +import ActionIcon from '../../ActionIcon'; + +function convertClickHandler(clickProp, value, datum) { + if (clickProp && typeof clickProp === 'function') { + return () => clickProp(value, datum); + } + return clickProp; +} + +function convertHref(hrefProp, value, datum) { + return typeof hrefProp === 'function' + ? hrefProp(value, datum) + : hrefProp; +} + +export default function ActionGroupRenderer({ + value, + datum, + onView, + viewHref, + viewItemProps = {}, + onEdit, + editHref, + editItemProps = {}, + onDelete, + deleteHref, + deleteItemProps = {}, + children, +}) { + const showView = viewHref || onView; + const showEdit = editHref || onEdit; + const showDelete = deleteHref || onDelete; + + const { + handleView, + handleEdit, + handleDelete, + finalViewHref, + finalEditHref, + finalDeleteHref, + } = useMemo( + () => ({ + handleView: convertClickHandler(onView, value, datum), + handleEdit: convertClickHandler(onEdit, value, datum), + handleDelete: convertClickHandler(onDelete, value, datum), + finalViewHref: convertHref(viewHref, value, datum), + finalEditHref: convertHref(editHref, value, datum), + finalDeleteHref: convertHref(deleteHref, value, datum), + }), + [ + value, + datum, + onView, + onEdit, + onDelete, + viewHref, + editHref, + deleteHref, + ], + ); + + return ( +
+ {showView && ( + + )} + {showEdit && ( + + )} + {showDelete && ( + + )} + {children} +
+ ); +} diff --git a/src/components/dataDisplays/cellRenderers/index.js b/src/components/dataDisplays/cellRenderers/index.js index 0763ba44..bc779250 100644 --- a/src/components/dataDisplays/cellRenderers/index.js +++ b/src/components/dataDisplays/cellRenderers/index.js @@ -1,4 +1,5 @@ import DefaultRenderer from './DefaultRenderer'; +import ActionGroupRenderer from './ActionGroupRenderer'; import UserRenderer from './UserRenderer'; import LocationRenderer from './LocationRenderer'; import SpecifiedTimeRenderer from './SpecifiedTimeRenderer'; @@ -11,6 +12,7 @@ import SocialGroupRoleRenderer from './SocialGroupRoleRenderer'; export const cellRendererTypes = { default: 'default', + actionGroup: 'actionGroup', user: 'user', location: 'location', specifiedTime: 'specifiedTime', @@ -24,6 +26,7 @@ export const cellRendererTypes = { export const cellRenderers = { [cellRendererTypes.default]: DefaultRenderer, + [cellRendererTypes.actionGroup]: ActionGroupRenderer, [cellRendererTypes.user]: UserRenderer, [cellRendererTypes.location]: LocationRenderer, [cellRendererTypes.specifiedTime]: SpecifiedTimeRenderer, diff --git a/src/pages/fieldManagement/settings/CustomFieldTable.jsx b/src/pages/fieldManagement/settings/CustomFieldTable.jsx index aca7d70d..5c7ae78a 100644 --- a/src/pages/fieldManagement/settings/CustomFieldTable.jsx +++ b/src/pages/fieldManagement/settings/CustomFieldTable.jsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { useIntl } from 'react-intl'; import { get } from 'lodash-es'; @@ -6,8 +6,8 @@ import Grid from '@material-ui/core/Grid'; import Tooltip from '@material-ui/core/Tooltip'; import AddIcon from '@material-ui/icons/Add'; +import { cellRendererTypes } from '../../../components/dataDisplays/cellRenderers'; import useRemoveCustomField from '../../../models/site/useRemoveCustomField'; -import ActionIcon from '../../../components/ActionIcon'; import ButtonLink from '../../../components/ButtonLink'; import ConfirmDelete from '../../../components/ConfirmDelete'; import Text from '../../../components/Text'; @@ -62,6 +62,22 @@ export default function CustomFieldTable({ ); const fieldTypeName = fieldTypeDefinition.name; + const onViewCustomField = useCallback((_, field) => { + setPreviewInitialValue(field.defaultValue); + setPreviewField(field); + }, []); + + const deriveEditHref = useCallback( + (_, field) => + `/settings/fields/save-custom-field/${fieldTypeName}/${field.id}`, + [fieldTypeName], + ); + + const onDeleteCustomField = useCallback( + (_, field) => setDeleteField(field), + [], + ); + const tableColumns = useMemo( () => [ { @@ -89,30 +105,16 @@ export default function CustomFieldTable({ name: 'actions', labelId: 'ACTIONS', options: { - customBodyRender: (_, field) => ( -
- { - setPreviewInitialValue(field.defaultValue); - setPreviewField(field); - }} - /> - - setDeleteField(field)} - /> -
- ), + cellRenderer: cellRendererTypes.actionGroup, + cellRendererProps: { + onView: onViewCustomField, + editHref: deriveEditHref, + onDelete: onDeleteCustomField, + }, }, }, ], - [intl, fieldTypeName], + [onViewCustomField, deriveEditHref, onDeleteCustomField], ); const onCloseConfirmDelete = () => {