Skip to content

Commit

Permalink
Added EditableColumn component
Browse files Browse the repository at this point in the history
  • Loading branch information
SteRiccio committed Oct 14, 2024
1 parent 90131b9 commit 5ccdff0
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 72 deletions.
94 changes: 94 additions & 0 deletions webapp/components/DataGrid/EditableColumn.js
Original file line number Diff line number Diff line change
@@ -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 <div className={className}>{renderItem({ item })}</div>
}

return (
<div
className={classNames(className, { editing })}
onClick={onContainerClick}
onFocus={onContainerFocus}
onKeyDown={onContainerKeyDown}
onMouseOver={onContainerMouseOver}
onMouseLeave={onContainerMouseLeave}
role="button"
tabIndex={0}
>
{editing && renderItemEditing({ item })}
{!editing && renderItem({ item })}
{hovering && !editing && <ButtonIconEdit onClick={onEditClick} />}
</div>
)
}

EditableColumn.propTypes = {
canEdit: PropTypes.bool,
className: PropTypes.string,
item: PropTypes.object.isRequired,
renderItem: PropTypes.func.isRequired,
renderItemEditing: PropTypes.func.isRequired,
}
81 changes: 9 additions & 72 deletions webapp/views/App/views/Data/Records/RecordOwnerColumn.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
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'

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)
Expand All @@ -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 })
Expand Down Expand Up @@ -110,20 +54,13 @@ export const RecordOwnerColumn = (props) => {
}

return (
<div
className={classNames('record-owner-col', { editing })}
onClick={onContainerClick}
onFocus={onContainerFocus}
onKeyDown={onContainerKeyDown}
onMouseOver={onContainerMouseOver}
onMouseLeave={onContainerMouseLeave}
role="button"
tabIndex={0}
>
{editing && <RecordOwnerDropdown selectedUuid={ownerUuid} onChange={onChange} />}
{!editing && ownerName}
{hovering && !editing && <ButtonIconEdit onClick={onEditClick} />}
</div>
<EditableColumn
canEdit={canEdit}
className="record-owner-col"
item={record}
renderItem={({ item }) => Record.getOwnerName(item)}
renderItemEditing={() => <RecordOwnerDropdown selectedUuid={ownerUuid} onChange={onChange} />}
/>
)
}

Expand Down

0 comments on commit 5ccdff0

Please sign in to comment.