Skip to content

Commit

Permalink
fix: interpretations panel renders with flashing when liking or unlik…
Browse files Browse the repository at this point in the history
…ing an interpretation (#1600)

* fix: rendering a spinner based on fetching causes flash

* fix: dont use loader and mask when like/unliking

* fix: when liking just update the object instead of new request

* fix: unneeded changes

* fix: unneeded changes

* fix: more cleanup

* fix: set dirty so parent component refreshes interpretations list

---------

Co-authored-by: Edoardo Sabadelli <edoardo@dhis2.org>
  • Loading branch information
jenniferarnesen and edoardo committed Mar 5, 2024
1 parent 5a91391 commit bb32565
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const InterpretationModal = ({
})
const interpretation = data?.interpretation
const shouldRenderModalContent = !error && interpretation
const shouldCssHideModal = loading || isVisualizationLoading
const loadingInProgress = loading || isVisualizationLoading
const handleClose = () => {
if (isDirty) {
onInterpretationUpdate()
Expand All @@ -97,6 +97,13 @@ const InterpretationModal = ({
}
refetch({ id: interpretationId })
}

const onLikeToggled = ({ likedBy }) => {
setIsDirty(true)
interpretation.likedBy = likedBy
interpretation.likes = likedBy.length
}

const onInterpretationDeleted = () => {
setIsDirty(false)
onInterpretationUpdate()
Expand All @@ -111,7 +118,7 @@ const InterpretationModal = ({

return (
<>
{shouldCssHideModal && (
{loadingInProgress && (
<Layer>
<CenteredContent>
<CircularLoader />
Expand All @@ -122,7 +129,7 @@ const InterpretationModal = ({
fluid
onClose={handleClose}
className={cx(modalCSS.className, {
hidden: shouldCssHideModal,
hidden: loadingInProgress,
})}
dataTest="interpretation-modal"
>
Expand Down Expand Up @@ -183,6 +190,7 @@ const InterpretationModal = ({
downloadMenuComponent={
downloadMenuComponent
}
onLikeToggled={onLikeToggled}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const InterpretationThread = ({
fetching,
interpretation,
onInterpretationDeleted,
onLikeToggled,
initialFocus,
onThreadUpdated,
downloadMenuComponent: DownloadMenu,
Expand Down Expand Up @@ -52,6 +53,7 @@ const InterpretationThread = ({
<Interpretation
currentUser={currentUser}
interpretation={interpretation}
onLikeToggled={onLikeToggled}
onReplyIconClick={
interpretationAccess.comment
? () => focusRef.current?.focus()
Expand Down Expand Up @@ -166,6 +168,7 @@ InterpretationThread.propTypes = {
fetching: PropTypes.bool.isRequired,
interpretation: PropTypes.object.isRequired,
onInterpretationDeleted: PropTypes.func.isRequired,
onLikeToggled: PropTypes.func.isRequired,
dashboardRedirectUrl: PropTypes.string,
downloadMenuComponent: PropTypes.oneOfType([
PropTypes.object,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const InterpretationList = ({
currentUser,
interpretations,
onInterpretationClick,
onLikeToggled,
onReplyIconClick,
refresh,
disabled,
Expand Down Expand Up @@ -65,6 +66,7 @@ export const InterpretationList = ({
interpretation={interpretation}
currentUser={currentUser}
onClick={onInterpretationClick}
onLikeToggled={onLikeToggled}
onReplyIconClick={onReplyIconClick}
onDeleted={refresh}
onUpdated={refresh}
Expand Down Expand Up @@ -120,6 +122,7 @@ InterpretationList.propTypes = {
interpretations: PropTypes.array.isRequired,
refresh: PropTypes.func.isRequired,
onInterpretationClick: PropTypes.func.isRequired,
onLikeToggled: PropTypes.func.isRequired,
onReplyIconClick: PropTypes.func.isRequired,
dashboardRedirectUrl: PropTypes.string,
disabled: PropTypes.bool,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,16 @@ export const InterpretationsUnit = forwardRef(
ref
) => {
const [isExpanded, setIsExpanded] = useState(true)
const [interpretations, setInterpretations] = useState([])
const showNoTimeDimensionHelpText =
type === 'eventVisualization' && !visualizationHasTimeDimension

const { data, loading, fetching, refetch } = useDataQuery(
const { loading, fetching, refetch } = useDataQuery(
interpretationsQuery,
{
lazy: true,
onComplete: (data) =>
setInterpretations(data.interpretations.interpretations),
}
)

Expand All @@ -82,6 +85,14 @@ export const InterpretationsUnit = forwardRef(
}
}, [type, id, renderId, refetch])

const onLikeToggled = ({ id, likedBy }) => {
const interpretation = interpretations.find(
(interp) => interp.id === id
)
interpretation.likedBy = likedBy
interpretation.likes = likedBy.length
}

return (
<div
className={cx('container', {
Expand Down Expand Up @@ -111,7 +122,7 @@ export const InterpretationsUnit = forwardRef(
<CircularLoader small />
</div>
)}
{data && (
{interpretations && (
<>
<InterpretationForm
currentUser={currentUser}
Expand All @@ -125,12 +136,11 @@ export const InterpretationsUnit = forwardRef(
/>
<InterpretationList
currentUser={currentUser}
interpretations={
data.interpretations.interpretations
}
interpretations={interpretations}
onInterpretationClick={
onInterpretationClick
}
onLikeToggled={onLikeToggled}
onReplyIconClick={onReplyIconClick}
refresh={onCompleteAction}
disabled={disabled}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,18 @@ export const Interpretation = ({
onReplyIconClick,
dashboardRedirectUrl,
isInThread,
onLikeToggled,
}) => {
const [isUpdateMode, setIsUpdateMode] = useState(false)
const [showSharingDialog, setShowSharingDialog] = useState(false)
const { toggleLike, isLikedByCurrentUser, toggleLikeInProgress } = useLike({
interpretation,
currentUser,
onComplete: onUpdated,
onComplete: (likedBy) =>
onLikeToggled({
id: interpretation.id,
likedBy,
}),
})
const shouldShowButton = Boolean(
!!onClick && !disabled & !dashboardRedirectUrl
Expand Down Expand Up @@ -180,6 +185,7 @@ Interpretation.propTypes = {
currentUser: PropTypes.object.isRequired,
interpretation: PropTypes.object.isRequired,
onDeleted: PropTypes.func.isRequired,
onLikeToggled: PropTypes.func.isRequired,
onReplyIconClick: PropTypes.func.isRequired,
onUpdated: PropTypes.func.isRequired,
dashboardRedirectUrl: PropTypes.string,
Expand Down
21 changes: 19 additions & 2 deletions src/components/Interpretations/common/Interpretation/useLike.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,28 @@ const useLike = ({ interpretation, currentUser, onComplete }) => {
const unlikeMutationRef = useRef({ resource, type: 'delete' })
const [like, { loading: likeLoading }] = useDataMutation(
likeMutationRef.current,
{ onComplete }
{
onComplete: () => {
const newLikedBy = interpretation.likedBy.concat({
id: currentUser.id,
})
setIsLikedByCurrentUser(true)
onComplete(newLikedBy)
},
}
)
const [unlike, { loading: unlikeLoading }] = useDataMutation(
unlikeMutationRef.current,
{ onComplete }
{
onComplete: () => {
const newLikedBy = interpretation.likedBy.filter(
(lb) => lb.id !== currentUser.id
)

setIsLikedByCurrentUser(false)
onComplete(newLikedBy)
},
}
)
const [isLikedByCurrentUser, setIsLikedByCurrentUser] = useState(false)
const toggleLike = () => {
Expand Down

0 comments on commit bb32565

Please sign in to comment.