0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-01-06 22:40:14 -05:00

Updated comment count to use the /comments/count API

refs https://github.com/TryGhost/Team/issues/1763

We still need to use the pagination for the other checks because these
are based on how many comments are visible, which includes deleted or
hidden comments.

By using the /comments/count API we ensure that any changes to the
calculation of comments is replicated by both the comment_count
helper, as well as the comments-ui
This commit is contained in:
Fabien "egg" O'Carroll 2022-08-08 17:29:38 +01:00 committed by Fabien 'egg' O'Carroll
parent 3a48518407
commit 4b453a8b3a
3 changed files with 34 additions and 12 deletions

View file

@ -69,7 +69,7 @@ export default class App extends React.Component {
try {
// Fetch data from API, links, preview, dev sources
const {site, member} = await this.fetchApiData();
const {comments, pagination} = await this.fetchComments();
const {comments, pagination, count} = await this.fetchComments();
const state = {
site,
@ -77,7 +77,8 @@ export default class App extends React.Component {
action: 'init:success',
initStatus: 'success',
comments,
pagination
pagination,
commentCount: count
};
this.setState(state);
@ -173,11 +174,15 @@ export default class App extends React.Component {
/** Fetch first few comments */
async fetchComments() {
const data = await this.GhostApi.comments.browse({page: 1, postId: this.state.postId});
const dataPromise = this.GhostApi.comments.browse({page: 1, postId: this.state.postId});
const countPromise = this.GhostApi.comments.count({postId: this.state.postId});
const [data, count] = await Promise.all([dataPromise, countPromise]);
return {
comments: data.comments,
pagination: data.meta.pagination
pagination: data.meta.pagination,
count: count
};
}
@ -277,7 +282,7 @@ export default class App extends React.Component {
/**Get final App level context from App state*/
getContextFromState() {
const {action, popupNotification, customSiteUrl, member, comments, pagination, postId, admin, popup} = this.state;
const {action, popupNotification, customSiteUrl, member, comments, pagination, commentCount, postId, admin, popup} = this.state;
return {
action,
popupNotification,
@ -286,6 +291,7 @@ export default class App extends React.Component {
admin,
comments,
pagination,
commentCount,
postId,
title: this.props.title,
showCount: this.props.showCount,

View file

@ -46,22 +46,20 @@ const CommentsBoxTitle = ({title, showCount, count}) => {
const CommentsBoxContent = (props) => {
const [isEditing, setIsEditing] = useState(false);
const {pagination, member, comments, commentsEnabled, title, showCount} = useContext(AppContext);
const {pagination, member, comments, commentCount, commentsEnabled, title, showCount} = useContext(AppContext);
const commentsElements = comments.slice().reverse().map(comment => <Comment isEditing={isEditing} comment={comment} key={comment.id} updateIsEditing={setIsEditing} />);
const commentsCount = pagination?.total || 0;
const paidOnly = commentsEnabled === 'paid';
const isPaidMember = member && !!member.paid;
useEffect(() => {
const elem = document.getElementById(ROOT_DIV_ID);
// Check scroll position
if (elem && window.location.hash === `#ghost-comments`) {
// Only scroll if the user didn't scroll by the time we loaded the comments
// We could remove this, but if the network connection is slow, we risk having a page jump when the user already started scrolling
if (window.scrollY === 0) {
if (window.scrollY === 0) {
// This is a bit hacky, but one animation frame is not enough to wait for the iframe height to have changed and the DOM to be updated correctly before scrolling
requestAnimationFrame(() => {
requestAnimationFrame(() => {
@ -74,14 +72,14 @@ const CommentsBoxContent = (props) => {
return (
<>
<CommentsBoxTitle title={title} showCount={showCount} count={commentsCount}/>
<CommentsBoxTitle title={title} showCount={showCount} count={commentCount}/>
<Pagination />
<div className={!pagination ? 'mt-4' : ''}>
{commentsElements}
</div>
<div>
{ !isEditing
? (member ? (isPaidMember || !paidOnly ? <Form commentsCount={commentsCount} /> : <CTABox isFirst={commentsCount === 0} isPaid={paidOnly} />) : <CTABox isFirst={commentsCount === 0} isPaid={paidOnly} />)
? (member ? (isPaidMember || !paidOnly ? <Form commentsCount={commentCount} /> : <CTABox isFirst={pagination?.total === 0} isPaid={paidOnly} />) : <CTABox isFirst={pagination?.total === 0} isPaid={paidOnly} />)
: null
}
</div>

View file

@ -102,6 +102,24 @@ function setupGhostApi({siteUrl = window.location.origin, apiUrl, apiKey}) {
let firstCommentsLoadedAt = null;
api.comments = {
async count({postId}) {
const url = endpointFor({type: 'members', resource: 'comments/counts'});
const response = await makeRequest({
url,
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
credentials: 'same-origin',
body: JSON.stringify({
ids: [postId]
})
});
const json = await response.json();
return json[postId];
},
browse({page, postId}) {
firstCommentsLoadedAt = firstCommentsLoadedAt ?? new Date().toISOString();