Skip to content

Commit

Permalink
Improve and fix workflow for adding justifications.
Browse files Browse the repository at this point in the history
  • Loading branch information
mo-fu committed Jul 2, 2024
1 parent 48e92d4 commit 0ddb0a4
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 56 deletions.
16 changes: 4 additions & 12 deletions ui/src/contribution/entity/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import {
selectSelectedEntity,
selectTagDefinitions,
selectMatchTagDefinitionList,
selectTagRowDefs,
selectJustificationForSelectedEntity
selectTagRowDefs
} from './selectors'
import {
getContributionEntitiesAction,
Expand Down Expand Up @@ -243,11 +242,9 @@ export function EntityConflictBody({
}

function NoConflictBody({
contributionJustification,
entity
contributionJustification
}: {
contributionJustification: string | undefined
entity: EntityWithDuplicates
}) {
const dispatch = useDispatch()
return (
Expand Down Expand Up @@ -360,10 +357,7 @@ export function EntitySimilarityItem({
) {
return (
<>
<NoConflictBody
contributionJustification={contributionJustification}
entity={entity}
/>
<NoConflictBody contributionJustification={contributionJustification} />
<JustificationModal putDuplicateCallback={putDuplicateCallback} />
</>
)
Expand Down Expand Up @@ -410,9 +404,7 @@ export function EntitySimilarityItem({
entity.justificationTxt === undefined &&
contributionJustification === undefined
) {
dispatch(
openJustificationInput(entity.idPersistent)
)
dispatch(openJustificationInput())
} else {
putDuplicateCallback({
idEntityOriginPersistent:
Expand Down
9 changes: 3 additions & 6 deletions ui/src/contribution/entity/components/buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { loadContributionDetails } from '../../thunks'
import { selectCompleteEntityAssignment, selectSelectedEntity } from '../selectors'
import { completeEntityAssignment } from '../thunks'
import { useAppDispatch, useAppSelector } from '../../../hooks'
import { openJustificationInput } from '../slice'
import { clearContributionEntityState, openJustificationInput } from '../slice'

export function CompleteAssignmentButton({
idContributionPersistent
Expand All @@ -31,6 +31,7 @@ export function CompleteAssignmentButton({
dispatch(
loadContributionDetails(idContributionPersistent)
)
dispatch(clearContributionEntityState())
navigate(
`/contribute/${idContributionPersistent}/complete`
)
Expand All @@ -50,11 +51,7 @@ export function ChangeJustificationButton() {
return <></>
}
return (
<Button
onClick={() =>
dispatch(openJustificationInput(selectedEntity.idPersistent))
}
>
<Button onClick={() => dispatch(openJustificationInput())}>
Edit Justification
</Button>
)
Expand Down
35 changes: 15 additions & 20 deletions ui/src/contribution/entity/components/modals.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ChangeEvent, useState } from 'react'
import { ChangeEvent, useEffect, useState } from 'react'

Check warning on line 1 in ui/src/contribution/entity/components/modals.tsx

View workflow job for this annotation

GitHub Actions / frontend

'useEffect' is defined but never used. Allowed unused vars must match /^_/u
import { Button, Col, FormCheck, Modal, Row } from 'react-bootstrap'
import { useAppDispatch, useAppSelector } from '../../../hooks'
import { FormField } from '../../../util/form'
import { PutDuplicateCallback } from '../components'
import {
selectLastMatchHit,
selectJustificationForEntityId,
selectShowTagDefinitionsMenu,
selectEntities,
selectJustificationForSelectedEntity
selectSelectedEntity,
selectShowJustificationInput
} from '../selectors'

import {
Expand All @@ -22,28 +22,25 @@ import { selectContributionJustification } from '../../selectors'
import { CompleteAssignmentButton } from './buttons'
import { ColumnMenuBody } from '../../../column_menu/components/menu'
import { getContributionTagInstances } from '../thunks'
import { EntityWithDuplicates } from '../state'

export function JustificationModal({
putDuplicateCallback
}: {
putDuplicateCallback: PutDuplicateCallback
}) {
const contributionJustification = useAppSelector(selectContributionJustification)
const showForId = useAppSelector(selectJustificationForEntityId)
const justificationForSelectedEntity = useAppSelector(
selectJustificationForSelectedEntity
)
const show = useAppSelector(selectShowJustificationInput)
const selectedEntity = useAppSelector(selectSelectedEntity)
const dispatch = useAppDispatch()
const show = showForId !== undefined
const closeModalCallback = () => dispatch(closeJustificationInput())
return (
<Modal show={show} onHide={closeModalCallback}>
<Modal.Header closeButton={true}>Add Justification</Modal.Header>
<Modal.Body>
{show && (
{show && selectedEntity !== undefined && (
<JustificationModalBody
idEntityPersistent={showForId}
entityJustification={justificationForSelectedEntity}
entity={selectedEntity}
contributionJustification={contributionJustification}
putDuplicateCallback={putDuplicateCallback}
closeModalCallback={closeModalCallback}
Expand All @@ -55,30 +52,28 @@ export function JustificationModal({
}

function JustificationModalBody({
idEntityPersistent,
entityJustification,
entity,
contributionJustification,
putDuplicateCallback,
closeModalCallback
}: {
idEntityPersistent: string
entityJustification: string | undefined
entity: EntityWithDuplicates
contributionJustification: string | undefined
putDuplicateCallback: PutDuplicateCallback
closeModalCallback: VoidFunction
}) {
const entityJustification = entity.justificationTxt
const [justification, setJustification] = useState(
entityJustification ?? contributionJustification ?? ''
)
const [keepJustification, setKeepJustification] = useState(
entityJustification === undefined && contributionJustification !== undefined
)
const [keepJustification, setKeepJustification] = useState(false)
const button = (
<Button
onClick={() =>
putDuplicateCallback({
idEntityOriginPersistent: idEntityPersistent,
idEntityDestinationPersistent: undefined,
idEntityOriginPersistent: entity.idPersistent,
idEntityDestinationPersistent:
entity.assignedDuplicate.value?.idPersistent,
justificationTxt: justification,
keepJustificationForAll: keepJustification,
onSuccess: closeModalCallback
Expand Down
2 changes: 1 addition & 1 deletion ui/src/contribution/entity/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export function mkCellContentCallback(
} else {
replaceInfo = new AssignType(
true,
entityGroup.similarEntities.value[col_idx - 2].idPersistent ==
entityGroup.similarEntities.value[col_idx - 2]?.idPersistent ==
entityGroup.assignedDuplicate.value?.idPersistent
)
}
Expand Down
4 changes: 2 additions & 2 deletions ui/src/contribution/entity/selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ export const selectCompleteEntityAssignment = createSelector(
(state) => state.completeEntityAssignment
)

export const selectJustificationForEntityId = createSelector(
export const selectShowJustificationInput = createSelector(
selectContributionEntity,
(state) => state.justificationDialogForEntity
(state) => state.showJustificationDialog
)

export const selectJustificationForSelectedEntity = createSelector(
Expand Down
16 changes: 9 additions & 7 deletions ui/src/contribution/entity/slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,14 +296,11 @@ export const contributionEntitySlice = createSlice({
}
state.hitLastMatch = true
},
openJustificationInput(
state: ContributionEntityState,
action: PayloadAction<string>
) {
state.justificationDialogForEntity = action.payload
openJustificationInput(state: ContributionEntityState) {
state.showJustificationDialog = true
},
closeJustificationInput(state: ContributionEntityState) {
state.justificationDialogForEntity = undefined
state.showJustificationDialog = false
},
clearHitLastMatch(state: ContributionEntityState) {
state.hitLastMatch = false
Expand All @@ -313,6 +310,10 @@ export const contributionEntitySlice = createSlice({
action: PayloadAction<{ idx: number; width: number }>
) {
state.matchWidths[action.payload.idx] = action.payload.width
},
clearContributionEntityState(state: ContributionEntityState) {
state.selectedEntityIdx = undefined
state.hitLastMatch = false
}
}
})
Expand Down Expand Up @@ -508,5 +509,6 @@ export const {
clearHitLastMatch,
setColumnWidth,
openJustificationInput,
closeJustificationInput
closeJustificationInput,
clearContributionEntityState
} = contributionEntitySlice.actions
8 changes: 4 additions & 4 deletions ui/src/contribution/entity/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export interface ContributionEntityState {
selectedEntityIdx?: number
hitLastMatch: boolean
matchWidths: number[]
justificationDialogForEntity: string | undefined
showJustificationDialog: boolean
}
export function newContributionEntityState({
entities = newRemote([]),
Expand All @@ -132,7 +132,7 @@ export function newContributionEntityState({
selectedEntityIdx = undefined,
hitLastMatch = false,
matchWidths = [200, 200],
justificationDialogForEntity = undefined
showJustificationDialog = false
}: {
entities?: RemoteInterface<EntityWithDuplicates[]>
entityMap?: { [key: string]: number }
Expand All @@ -143,7 +143,7 @@ export function newContributionEntityState({
selectedEntityIdx?: number
hitLastMatch?: boolean
matchWidths?: number[]
justificationDialogForEntity?: string | undefined
showJustificationDialog?: boolean
}): ContributionEntityState {
let newEntityMap: { [key: string]: number },
newTagDefinitionMap: { [key: string]: number }
Expand Down Expand Up @@ -176,6 +176,6 @@ export function newContributionEntityState({
selectedEntityIdx: selectedEntityIdx,
hitLastMatch: hitLastMatch,
matchWidths: matchWidths,
justificationDialogForEntity
showJustificationDialog: showJustificationDialog
}
}
2 changes: 1 addition & 1 deletion ui/src/contribution/entity/thunks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export function putDuplicateAction({
rsp.status == 400 &&
json['msg'] == 'Entity justification required.'
) {
dispatch(openJustificationInput(idEntityOriginPersistent))
dispatch(openJustificationInput())
return false
}
dispatch(
Expand Down
6 changes: 3 additions & 3 deletions ui/src/entity/__tests__/components.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@
*/
import { render, screen } from '@testing-library/react'
import { AddEntityForm } from '../components'
import { Remote } from '../../util/state'
import { newRemote } from '../../util/state'
import userEvent from '@testing-library/user-event'

describe('Add entity form', () => {
test('renders correctly', async () => {
const state = new Remote(false)
const state = newRemote(false)
render(<AddEntityForm state={state} addEntityCallback={jest.fn()} />)
const inputs = screen.getAllByRole('textbox')
expect(inputs.length).toEqual(2)
const button = screen.getByRole('button')
expect(button.textContent).toEqual('Add Entity')
})
test('can submit', async () => {
const state = new Remote(false)
const state = newRemote(false)
const addEntityCallback = jest.fn()
render(<AddEntityForm state={state} addEntityCallback={addEntityCallback} />)
const textBoxes = screen.getAllByRole('textbox')
Expand Down

0 comments on commit 0ddb0a4

Please sign in to comment.