diff --git a/webapp/components/DataGrid/EditableColumn.js b/webapp/components/DataGrid/EditableColumn.js new file mode 100644 index 0000000000..e0e1e8173b --- /dev/null +++ b/webapp/components/DataGrid/EditableColumn.js @@ -0,0 +1,94 @@ +import React, { useCallback, useState } from 'react' +import classNames from 'classnames' +import PropTypes from 'prop-types' + +import { ButtonIconEdit } from '@webapp/components' +import { KeyboardKeys } from '@webapp/utils/keyboardKeys' + +export const EditableColumn = (props) => { + const { canEdit, className, item, renderItem, renderItemEditing } = props + + const [state, setState] = useState({ editing: false, hovering: false }) + const { editing, hovering } = state + + const setHovering = useCallback( + (hoveringNew) => { + if (hoveringNew !== hovering) { + setState((statePrev) => ({ ...statePrev, hovering: hoveringNew })) + } + }, + [hovering] + ) + + const setEditing = useCallback( + (editingNew) => { + if (editingNew !== editing) { + setState((statePrev) => ({ ...statePrev, editing: editingNew })) + } + }, + [editing] + ) + + const onContainerMouseOver = useCallback(() => setHovering(true), [setHovering]) + const onContainerMouseLeave = useCallback(() => setHovering(false), [setHovering]) + + const onContainerClick = useCallback( + (e) => { + // prevent table row selection on click + if (editing) { + e.stopPropagation() + e.preventDefault() + } + }, + [editing] + ) + + const onContainerFocus = useCallback(() => setHovering(true), [setHovering]) + + const onContainerKeyDown = useCallback( + (e) => { + if (e.key === KeyboardKeys.Space) { + setEditing(true) + } + }, + [setEditing] + ) + + const onEditClick = useCallback( + (e) => { + e.stopPropagation() + e.preventDefault() + setEditing(true) + }, + [setEditing] + ) + + if (!canEdit) { + return
{renderItem({ item })}
+ } + + return ( +
+ {editing && renderItemEditing({ item })} + {!editing && renderItem({ item })} + {hovering && !editing && } +
+ ) +} + +EditableColumn.propTypes = { + canEdit: PropTypes.bool, + className: PropTypes.string, + item: PropTypes.object.isRequired, + renderItem: PropTypes.func.isRequired, + renderItemEditing: PropTypes.func.isRequired, +} diff --git a/webapp/views/App/views/Data/Records/RecordOwnerColumn.js b/webapp/views/App/views/Data/Records/RecordOwnerColumn.js index 6fe2301169..cc8c300b23 100644 --- a/webapp/views/App/views/Data/Records/RecordOwnerColumn.js +++ b/webapp/views/App/views/Data/Records/RecordOwnerColumn.js @@ -1,17 +1,15 @@ -import React, { useCallback, useState } from 'react' +import React, { useCallback } from 'react' import { useDispatch } from 'react-redux' -import classNames from 'classnames' import PropTypes from 'prop-types' import * as Record from '@core/record/record' import * as User from '@core/user/user' -import { ButtonIconEdit } from '@webapp/components' import * as API from '@webapp/service/api' import { useSurveyId } from '@webapp/store/survey' import { useAuthCanCleanseRecords } from '@webapp/store/user/hooks' import { DialogConfirmActions } from '@webapp/store/ui' -import { KeyboardKeys } from '@webapp/utils/keyboardKeys' +import { EditableColumn } from '@webapp/components/DataGrid/EditableColumn' import { RecordOwnerDropdown } from './RecordOwnerDropdown' @@ -19,8 +17,6 @@ export const RecordOwnerColumn = (props) => { const { item: record, onRecordsUpdate } = props const dispatch = useDispatch() - const [state, setState] = useState({ editing: false, hovering: false }) - const { editing, hovering } = state const surveyId = useSurveyId() const ownerUuid = Record.getOwnerUuid(record) @@ -29,58 +25,6 @@ export const RecordOwnerColumn = (props) => { const canEdit = useAuthCanCleanseRecords() - const setHovering = useCallback( - (hoveringNew) => { - if (hoveringNew !== hovering) { - setState((statePrev) => ({ ...statePrev, hovering: hoveringNew })) - } - }, - [hovering] - ) - - const setEditing = useCallback( - (editingNew) => { - if (editingNew !== editing) { - setState((statePrev) => ({ ...statePrev, editing: editingNew })) - } - }, - [editing] - ) - - const onContainerMouseOver = useCallback(() => setHovering(true), [setHovering]) - const onContainerMouseLeave = useCallback(() => setHovering(false), [setHovering]) - - const onContainerClick = useCallback( - (e) => { - // prevent table row selection on click - if (editing) { - e.stopPropagation() - e.preventDefault() - } - }, - [editing] - ) - - const onContainerFocus = useCallback(() => setHovering(true), [setHovering]) - - const onContainerKeyDown = useCallback( - (e) => { - if (e.key === KeyboardKeys.Space) { - setEditing(true) - } - }, - [setEditing] - ) - - const onEditClick = useCallback( - (e) => { - e.stopPropagation() - e.preventDefault() - setEditing(true) - }, - [setEditing] - ) - const onChangeConfirmed = useCallback( async ({ selectedOwnerUuid }) => { await API.updateRecordOwner({ surveyId, recordUuid, ownerUuid: selectedOwnerUuid }) @@ -110,20 +54,13 @@ export const RecordOwnerColumn = (props) => { } return ( -
- {editing && } - {!editing && ownerName} - {hovering && !editing && } -
+ Record.getOwnerName(item)} + renderItemEditing={() => } + /> ) }