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={() => }
+ />
)
}