UX: improve blank page syndrome on the user messages page (#14165)

The user-topic-list template is also in use in other places when we want to improve blank page syndrome, so this PR is a preparation for that changes as well.
This commit is contained in:
Andrei Prigorshnev 2021-08-26 21:38:34 +04:00 committed by GitHub
parent d11f19f099
commit 9415fecfd0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 98 additions and 30 deletions

View File

@ -19,6 +19,12 @@ export default Controller.extend(BulkTopicSelection, {
channel: null,
tagsForUser: null,
pmTopicTrackingState: null,
incomingCount: reads("pmTopicTrackingState.newIncoming.length"),
@discourseComputed("emptyState", "model.topics.length", "incomingCount")
showEmptyStatePlaceholder(emptyState, topicsLength, incomingCount) {
return emptyState && topicsLength === 0 && incomingCount === 0;
},
saveScrollPosition() {
this.session.set("topicListScrollPosition", $(window).scrollTop());
@ -29,8 +35,6 @@ export default Controller.extend(BulkTopicSelection, {
this.set("application.showFooter", !this.get("model.canLoadMore"));
},
incomingCount: reads("pmTopicTrackingState.newIncoming.length"),
@discourseComputed("filter", "model.topics.length")
showResetNew(filter, hasTopics) {
return filter === NEW_FILTER && hasTopics;

View File

@ -3,6 +3,8 @@ import UserAction from "discourse/models/user-action";
import UserTopicListRoute from "discourse/routes/user-topic-list";
import { findOrResetCachedTopicList } from "discourse/lib/cached-topic-list";
import { action } from "@ember/object";
import { iconHTML } from "discourse-common/lib/icon-library";
import getURL from "discourse-common/lib/get-url";
export const NEW_FILTER = "new";
export const UNREAD_FILTER = "unread";
@ -61,6 +63,7 @@ export default (inboxType, path, filter) => {
inbox: inboxType,
pmTopicTrackingState:
userPrivateMessagesController.pmTopicTrackingState,
emptyState: this.emptyState(),
});
userTopicsListController.subscribe();
@ -74,6 +77,15 @@ export default (inboxType, path, filter) => {
this.searchService.set("contextType", "private_messages");
},
emptyState() {
const title = I18n.t("user.no_messages_title");
const body = I18n.t("user.no_messages_body", {
aboutUrl: getURL("/about"),
icon: iconHTML("envelope"),
}).htmlSafe();
return { title, body };
},
deactivate() {
this.controllerFor("user-topics-list").unsubscribe();

View File

@ -1,11 +1,19 @@
{{#unless site.mobileView}}
{{#if showToggleBulkSelect}}
{{bulk-select-button canDoBulkActions=true selected=selected action=(route-action "refresh")}}
{{/if}}
{{/unless}}
{{#if showEmptyStatePlaceholder}}
<div class="empty-state">
<span class="empty-state-title">{{emptyState.title}}</span>
<div class="empty-state-body">
<p>{{emptyState.body}}</p>
</div>
</div>
{{else}}
{{#unless site.mobileView}}
{{#if showToggleBulkSelect}}
{{bulk-select-button canDoBulkActions=true selected=selected action=(route-action "refresh")}}
{{/if}}
{{/unless}}
{{#load-more class="paginated-topics-list" selector=".paginated-topics-list .topic-list tr" action=(action "loadMore")}}
{{topic-dismiss-buttons
{{#load-more class="paginated-topics-list" selector=".paginated-topics-list .topic-list tr" action=(action "loadMore")}}
{{topic-dismiss-buttons
position="top"
selectedTopics=selected
model=model
@ -13,27 +21,27 @@
showDismissRead=showDismissRead
resetNew=(action "resetNew")}}
{{#if (gt incomingCount 0)}}
<div class="show-mores">
<a tabindex="0" href {{action "showInserted"}} class="alert alert-info clickable">
{{count-i18n key="topic_count_" suffix="latest" count=incomingCount}}
</a>
</div>
{{/if}}
{{#if (gt incomingCount 0)}}
<div class="show-mores">
<a tabindex="0" href {{action "showInserted"}} class="alert alert-info clickable">
{{count-i18n key="topic_count_" suffix="latest" count=incomingCount}}
</a>
</div>
{{/if}}
{{basic-topic-list topicList=model
hideCategory=hideCategory
showPosters=showPosters
bulkSelectEnabled=bulkSelectEnabled
selected=selected
tagsForUser=tagsForUser
onScroll=saveScrollPosition
canBulkSelect=canBulkSelect
scrollOnLoad=true
toggleBulkSelect=(action "toggleBulkSelect")
updateAutoAddTopicsToBulkSelect=(action "updateAutoAddTopicsToBulkSelect")}}
{{basic-topic-list topicList=model
hideCategory=hideCategory
showPosters=showPosters
bulkSelectEnabled=bulkSelectEnabled
selected=selected
tagsForUser=tagsForUser
onScroll=saveScrollPosition
canBulkSelect=canBulkSelect
scrollOnLoad=true
toggleBulkSelect=(action "toggleBulkSelect")
updateAutoAddTopicsToBulkSelect=(action "updateAutoAddTopicsToBulkSelect")}}
{{topic-dismiss-buttons
{{topic-dismiss-buttons
position="bottom"
selectedTopics=selected
model=model
@ -41,5 +49,6 @@
showDismissRead=showDismissRead
resetNew=(action "resetNew")}}
{{conditional-loading-spinner condition=model.loadingMore}}
{{/load-more}}
{{conditional-loading-spinner condition=model.loadingMore}}
{{/load-more}}
{{/if}}

View File

@ -546,3 +546,46 @@ acceptance(
});
}
);
acceptance("User Private Messages - user with no messages", function (needs) {
needs.user();
needs.pretender((server, helper) => {
const emptyResponse = {
topic_list: {
topics: [],
},
};
const apiUrls = [
"/topics/private-messages-all/:username.json",
"/topics/private-messages-all-sent/:username.json",
"/topics/private-messages-all-new/:username.json",
"/topics/private-messages-all-unread/:username.json",
"/topics/private-messages-all-archive/:username.json",
];
apiUrls.forEach((url) => {
server.get(url, () => {
return helper.response(emptyResponse);
});
});
});
test("It renders the empty state panel", async function (assert) {
await visit("/u/charlie/messages");
assert.ok(exists("div.empty-state"));
await visit("/u/charlie/messages/sent");
assert.ok(exists("div.empty-state"));
await visit("/u/charlie/messages/new");
assert.ok(exists("div.empty-state"));
await visit("/u/charlie/messages/unread");
assert.ok(exists("div.empty-state"));
await visit("/u/charlie/messages/archive");
assert.ok(exists("div.empty-state"));
});
});