-
Notifications
You must be signed in to change notification settings - Fork 52
pkp/pkp-lib#11327 Implement public facing UI for user comments #659
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
30c85fe
to
238b189
Compare
2f3351f
to
1f2de49
Compare
1f2de49
to
c528830
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @taslangraham. I'll let @jardakotesovec comment on anything specific about the Vue implementations, but it overall looks good to me. Just a few questions.
@@ -0,0 +1,108 @@ | |||
<template> | |||
<PkpModalBody> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The close button isn't highlighting and being treated as a clickable element by the mouse. It's still keyboard navigable, but it's not receiving the typical visual feedback from the pointer.
|
||
<div v-if="isLatestPublication && !!currentUser"> | ||
<PkpTextarea | ||
placeholder="What do you think about this publication? Type your comments here." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The placeholder should probably be localized too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.. and also label is essential for accessibility.
So we need to pass the same text as label. Because screen readers are somewhat inconsistent how they present placeholder.. And add prop on PkpTextarea to hide it (only for screenreaders).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To give you heads up. After we merge this version.. I will start gradually refining some of the components there.. and possibly reorganise things once I have good styling strategy settled. I would probably make these adjustments myself to see it in practice and just ask you for review. Lets see how that goes.
src/frontend/components/PkpAvatarInitials/pkpAvatarInitials.vue
Outdated
Show resolved
Hide resolved
@@ -13,12 +13,15 @@ const props = defineProps({ | |||
type: Boolean, | |||
default: false, | |||
}, | |||
/** Use when this button represents an action such as delete, go back, revert or cancel. */ | |||
isWarnable: Boolean, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will confirm this one with Devika.. maybe we can have just primary and secondary. Goal here will be again just have as least variants as possible.. so its easier to create styling across the themes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any updates on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most likely we will be fine just using the primary&secondary styling. So lets stick with that for now. Primary would be used for delete button, and secondary for cancel.
@@ -68,6 +68,9 @@ import { | |||
} from 'reka-ui'; | |||
import PkpIcon from '@/frontend/components/PkpIcon/PkpIcon.vue'; | |||
import {useLocalize} from '@/composables/useLocalize'; | |||
const {t} = useLocalize(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Originally I thought that we will just pass the labels via props. . thats pattern we used to do.
But good middle ground is probably just manually use setLocaleKeys
as you did and than still use nice t
in the code.
Thats why I have not included useLocalise. So lets include it.. but lets make copy and call it usePkpLocalise..
|
||
<div v-if="isLatestPublication && !!currentUser"> | ||
<PkpTextarea | ||
placeholder="What do you think about this publication? Type your comments here." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.. and also label is essential for accessibility.
So we need to pass the same text as label. Because screen readers are somewhat inconsistent how they present placeholder.. And add prop on PkpTextarea to hide it (only for screenreaders).
import {usePkpModal} from '@/frontend/composables/usePkpModal'; | ||
import {usePkpFetch} from '@/frontend/composables/usePkpFetch'; | ||
import {useUrl} from '@/frontend/composables/usePkpUrl'; | ||
import {useDate} from '@/composables/useDate'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hesitant to bring useDate as its quite sizeable.. But it would be good to have it.. so lets stick with it.. lets just make copy as well.
And I will iterate on it later to see whether I can make the dependency smaller.. or fine other way to do it.. but its good to have this abstracted in composable.
commentText.value = ''; | ||
// Add the new comment to the top of the comments list. | ||
comments.value.unshift(data); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once we update something via API - its best to reload the data and consider that as source of the truth.
Doing optimistic update on top of it is fine to make it bit faster. But in general for simplicity - I basically just call API for update and than refresh the data. So here doing the same would be fine as well. As long as there is indication that the submit is being processed its fine to show it with bit of delay.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, the simpler approach would be to refresh the data via API call.
However, I ran into a few concerns/roadblocks trying to refresh an entire list built from multiple paginated responses.
The challenge: when a user adds a new comment, it will be available on page 1 of the paginated results (most recent items comes first). To update the list via API to include the new comment, while preserving items already shown, I’d need to refetch items from page 1 up to the current page.
Options I’ve considered:
-
Refetch pages 1 to current
- would work, but not performant. Also, the new item on page 1 pushes another off and we might lose an item after finish fetching because it was pushed to another page not in the range(pages 1 to current) fetched.
-
Just fetch for page 1 where the new comment is expected to be and update that portion of the list
there's possibility that moderators approve new comments during the same time span, and those could potentially end up on that list returned from API depending on when they were created, and potentially displacing the expected new comment -
Single request with
pageSize = current length of comments + 1
(+1 to compensate for the newly added comment)- More efficient, but there's possibility that moderators approve new comments during the same time span, and those could potentially end up on that list returned from API depending on when they were created, thus potentially pushing more items off the final updated list shown to user.
-
Single request with
pageSize
= current length + 1 full page size- Benefits of number 3, but reduces the potential of a newly approved comment displacing one that was already visible to the user -- this is still a possibility though.
I initially went for the optimistic update, appending the created comment returned from the API, due to the challenges outlined above along with the fact that a newly created comment is only visible to the creator, and we just want to display it to them to confirm creation and to inform them that it will need approval before being visible to others.
I'm probably thinking about this incorrectly, so I'm open to feedback on how to approach this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On further thought, I don't think newly approved comments displacing others is a real concern at this time, and approach 3 or 4 should suffice in updating the list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see.. did not think about the "show more" impact here. In general "show more" is better to implemented with "cursor based" pagination.. as that ensures that newly added message (from anyone) does not mess up the list. But not sure how much effort that would be.. as we don't expect significant use - it will be fine either way.
Regarding what to do after posting new message. I think just going back to refetching "first page" and throwing rest should be fine.. and user can use show more again if they want to go back to the older messages. Since new messages is being added on top - I don't think that would be problematic.
pageCount.value = pagination.value.pageCount; | ||
showMoreCommentsCount.value = | ||
showMoreCommentsCount.value - props.itemsPerPage; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.. useFetchPaginated was not really created for "show more".. its done for using pagination.. so there would be opportunity to abstract that better.. but I think this is fine.
67ae0c2
to
2b21f3f
Compare
Thanks for the review @ewhanson & @jardakotesovec. @jardakotesovec I've made update based on feedback given. Please take a look. |
2b21f3f
to
39adda2
Compare
For pkp/pkp-lib#11327