Skip to content

Commit

Permalink
Merge pull request #2039 from chinmaykunkikar/listens-page-updates
Browse files Browse the repository at this point in the history
Add useful messages and call to actions for empty states on listens page
  • Loading branch information
MonkeyDo committed Jul 6, 2022
2 parents 22924c3 + b3352da commit de6f3d4
Show file tree
Hide file tree
Showing 12 changed files with 224 additions and 64 deletions.
21 changes: 19 additions & 2 deletions listenbrainz/webserver/static/css/follow.less
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,21 @@
}
}

.card-user-sn {
margin-bottom: 20px;

hr {
margin: 0px 2em;
border-top: 1px solid #eee;
}
}

.follower-following-pills {
padding-bottom: 10px;
padding: 20px 0px;

button {
margin: 0px 6px !important;
}
}

.follower-following-list,
Expand All @@ -59,7 +72,6 @@
overflow-y: scroll;
border-radius: 2px;
box-shadow: inset 0px 11px 8px -10px #ccc;
margin-bottom: 20px;

> * {
display: flex;
Expand All @@ -77,3 +89,8 @@
}
}
}

.follower-following-empty,
.similar-users-empty {
padding: 10px 20px;
}
37 changes: 37 additions & 0 deletions listenbrainz/webserver/static/css/listens-page.less
Original file line number Diff line number Diff line change
Expand Up @@ -596,3 +596,40 @@
overflow: hidden;
text-overflow: ellipsis;
}

#spacer {
margin-top: 54px;
}

.empty-listens {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: @orange;

.empty-text {
text-align: center;
margin: 4px 0px 0px;
color: @asphalt;
}

.empty-action {
margin-top: 12px;
padding: 0px 8em;
text-align: center;
color: @asphalt;
}

@media (max-width: @screen-sm) {
.empty-action {
padding: 0px 6em;
}
}

@media (max-width: @screen-xs) {
.empty-action {
padding: 0px 3em;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { includes as _includes } from "lodash";

import Pill from "../components/Pill";
import UserListModalEntry from "./UserListModalEntry";
import GlobalAppContext from "../utils/GlobalAppContext";

export type FollowerFollowingModalProps = {
user: ListenBrainzUser;
Expand All @@ -23,6 +24,9 @@ export default class FollowerFollowingModal extends React.Component<
FollowerFollowingModalProps,
FollowerFollowingModalState
> {
static contextType = GlobalAppContext;
declare context: React.ContextType<typeof GlobalAppContext>;

constructor(props: FollowerFollowingModalProps) {
super(props);
this.state = {
Expand All @@ -40,11 +44,63 @@ export default class FollowerFollowingModal extends React.Component<
updateFollowingList,
followerList,
followingList,
user,
} = this.props;
const { activeMode } = this.state;
const { currentUser } = this.context;

const activeModeList =
activeMode === "follower" ? followerList : followingList;

function renderFollowerFollowingList() {
if (activeModeList.length === 0) {
if (activeMode === "follower") {
return (
<>
<hr />
<div className="follower-following-empty text-center text-muted">
{user.name === currentUser?.name
? "You don't"
: `${user.name} doesn't`}{" "}
have any followers.
</div>
</>
);
}
return (
<>
<hr />
<div className="follower-following-empty text-center text-muted">
{user.name === currentUser?.name
? "You aren't"
: `${user.name} isn't`}{" "}
following anyone.
</div>
</>
);
}
return (
<div className="follower-following-list">
{activeModeList.map((listEntry: string) => {
const formattedAsUser: ListenBrainzUser = {
name: listEntry,
};
return (
<UserListModalEntry
mode="follow-following"
key={listEntry}
user={formattedAsUser}
loggedInUserFollowsUser={loggedInUserFollowsUser(
formattedAsUser
)}
updateFollowingList={updateFollowingList}
/>
);
})}
</div>
);
}

return (
<>
<div className="text-center follower-following-pills">
Expand All @@ -65,24 +121,7 @@ export default class FollowerFollowingModal extends React.Component<
</Pill>
</div>
</div>
<div className="follower-following-list">
{activeModeList.map((listEntry: string) => {
const formattedAsUser: ListenBrainzUser = {
name: listEntry,
};
return (
<UserListModalEntry
mode="follow-following"
key={listEntry}
user={formattedAsUser}
loggedInUserFollowsUser={loggedInUserFollowsUser(
formattedAsUser
)}
updateFollowingList={updateFollowingList}
/>
);
})}
</div>
{renderFollowerFollowingList()}
</>
);
}
Expand Down
34 changes: 29 additions & 5 deletions listenbrainz/webserver/static/js/src/follow/SimilarUsersModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,20 @@ const SimilarUsersModal = (props: SimilarUsersModalProps) => {
} = props;
const { currentUser } = React.useContext(GlobalAppContext);

return (
<>
<h3 className="text-center">
Users similar to {user.name === currentUser?.name ? "you" : user.name}
</h3>
const renderSimilarUsersList = React.useCallback(() => {
if (similarUsersList.length === 0) {
return (
<>
<hr />
<div className="similar-users-empty text-center text-muted">
Users with similar music tastes to{" "}
{user.name === currentUser?.name ? "you" : user.name} will appear
here.
</div>
</>
);
}
return (
<div className="similar-users-list">
{similarUsersList.map((listEntry: SimilarUser) => {
return (
Expand All @@ -41,6 +50,21 @@ const SimilarUsersModal = (props: SimilarUsersModalProps) => {
);
})}
</div>
);
}, [
similarUsersList,
user,
currentUser,
loggedInUserFollowsUser,
updateFollowingList,
]);

return (
<>
<h3 className="text-center" style={{ marginTop: "10px" }}>
Similar Users
</h3>
{renderSimilarUsersList()}
</>
);
};
Expand Down
31 changes: 18 additions & 13 deletions listenbrainz/webserver/static/js/src/follow/UserSocialNetwork.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isEmpty, isNil } from "lodash";
import * as React from "react";
import Card from "../components/Card";

import GlobalAppContext from "../utils/GlobalAppContext";
import FollowerFollowingModal from "./FollowerFollowingModal";
Expand Down Expand Up @@ -148,19 +149,23 @@ export default class UserSocialNetwork extends React.Component<
const { followerList, followingList, similarUsersList } = this.state;
return (
<>
<FollowerFollowingModal
user={user}
followerList={followerList}
followingList={followingList}
loggedInUserFollowsUser={this.loggedInUserFollowsUser}
updateFollowingList={this.updateFollowingList}
/>
<SimilarUsersModal
user={user}
similarUsersList={similarUsersList}
loggedInUserFollowsUser={this.loggedInUserFollowsUser}
updateFollowingList={this.updateFollowingList}
/>
<Card className="card-user-sn hidden-xs hidden-sm">
<FollowerFollowingModal
user={user}
followerList={followerList}
followingList={followingList}
loggedInUserFollowsUser={this.loggedInUserFollowsUser}
updateFollowingList={this.updateFollowingList}
/>
</Card>
<Card className="card-user-sn hidden-xs hidden-sm">
<SimilarUsersModal
user={user}
similarUsersList={similarUsersList}
loggedInUserFollowsUser={this.loggedInUserFollowsUser}
updateFollowingList={this.updateFollowingList}
/>
</Card>
</>
);
}
Expand Down
19 changes: 11 additions & 8 deletions listenbrainz/webserver/static/js/src/listens/ListenCountCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ const ListenCountCard = (props: ListenCountCardProps) => {
if (listenCount) {
content = (
<div>
{isCurrentUser
? "You have listened to"
: `${user.name} has listened to`}
{isCurrentUser ? "You have" : `${user.name} has`} listened to
<hr />
{listenCount.toLocaleString()}
<br />
Expand All @@ -28,11 +26,16 @@ const ListenCountCard = (props: ListenCountCardProps) => {
);
} else {
content = (
<p>
{isCurrentUser
? "You have not listened to any songs so far"
: `${user.name} has not listened to any songs so far`}
</p>
<>
<p className="text-muted">
{isCurrentUser ? "Your" : `${user.name}'s`} listens count
</p>
<hr style={{ margin: "10px 0px" }} />
<div style={{ fontSize: "14px" }} className="text-muted">
{isCurrentUser ? "You haven't" : `${user.name} hasn't`} listened to
any songs yet.
</div>
</>
);
}

Expand Down
35 changes: 24 additions & 11 deletions listenbrainz/webserver/static/js/src/user/Listens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { io, Socket } from "socket.io-client";
import { get, isEqual } from "lodash";
import { Integrations } from "@sentry/tracing";
import {
faCompactDisc,
faPencilAlt,
faThumbtack,
faTrashAlt,
Expand Down Expand Up @@ -785,7 +786,7 @@ export default class Listens extends React.Component<
listens?.[listens?.length - 1]?.listened_at <= oldestListenTs;
return (
<div role="main">
<h3>Recent listens</h3>
{listens.length === 0 ? <div id="spacer" /> : <h3>Recent listens</h3>}
<div className="row">
<div className="col-md-4 col-md-push-8">
{playingNowListen && this.getListenCard(playingNowListen)}
Expand All @@ -801,19 +802,31 @@ export default class Listens extends React.Component<
/>
)}
<ListenCountCard user={user} listenCount={listenCount} />
{user && (
<div
className="card hidden-xs hidden-sm"
style={{ paddingTop: "1.5em" }}
>
<UserSocialNetwork user={user} newAlert={newAlert} />
</div>
)}
{user && <UserSocialNetwork user={user} newAlert={newAlert} />}
</div>
<div className="col-md-8 col-md-pull-4">
{!listens.length && (
<div className="lead text-center">
<p>No listens yet</p>
<div className="empty-listens">
<FontAwesomeIcon icon={faCompactDisc as IconProp} size="10x" />
{currentUser?.name === user?.name ? (
<div className="lead empty-text">Get listening</div>
) : (
<div className="lead empty-text">
{user.name} hasn&apos;t listened to any songs yet.
</div>
)}

{currentUser?.name === user?.name && (
<div className="empty-action">
Import <a href="/profile/import/">your listening history</a>{" "}
from last.fm/libre.fm and track your listens by{" "}
<a href="/profile/music-services/details/">
connecting to a music streaming service
</a>
, or use <a href="/add-data/">one of these music players</a>{" "}
to start submitting your listens.
</div>
)}
</div>
)}
{listens.length > 0 && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<SimilarUsersModal /> renders 1`] = `"<h3 class=\\"text-center\\">Users similar to shivam-kapila</h3><div class=\\"similar-users-list\\"><div><div><a href=\\"/user/mr_monkey/reports/?range=month\\" target=\\"_blank\\" rel=\\"noopener noreferrer\\">mr_monkey</a></div></div></div>"`;
exports[`<SimilarUsersModal /> renders 1`] = `"<h3 class=\\"text-center\\" style=\\"margin-top: 10px;\\">Similar Users</h3><div class=\\"similar-users-list\\"><div><div><a href=\\"/user/mr_monkey/reports/?range=month\\" target=\\"_blank\\" rel=\\"noopener noreferrer\\">mr_monkey</a></div></div></div>"`;
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<UserSocialNetwork /> renders correctly 1`] = `"<div class=\\"text-center follower-following-pills\\"><div class=\\"btn-group btn-group-justified\\" role=\\"group\\"><button type=\\"button\\" style=\\"background: rgb(53, 48, 112); border: 2px solid #353070; font-weight: 700; color: white; border-radius: 24px; outline: none; padding: 3px 12px; margin: 2px 6px 12px 6px; box-sizing: border-box;\\">Followers (0)</button><button type=\\"button\\" style=\\"background: transparent; border: 2px solid #bbbbbb; color: rgb(187, 187, 187); border-radius: 24px; outline: none; padding: 3px 12px; margin: 2px 6px 12px 6px; box-sizing: border-box;\\">Following (0)</button></div></div><div class=\\"follower-following-list\\"></div><h3 class=\\"text-center\\">Users similar to bob</h3><div class=\\"similar-users-list\\"></div>"`;
exports[`<UserSocialNetwork /> renders correctly 1`] = `"<div class=\\"card card-user-sn hidden-xs hidden-sm\\"><div class=\\"text-center follower-following-pills\\"><div class=\\"btn-group btn-group-justified\\" role=\\"group\\"><button type=\\"button\\" style=\\"background: rgb(53, 48, 112); border: 2px solid #353070; font-weight: 700; color: white; border-radius: 24px; outline: none; padding: 3px 12px; margin: 2px 6px 12px 6px; box-sizing: border-box;\\">Followers (0)</button><button type=\\"button\\" style=\\"background: transparent; border: 2px solid #bbbbbb; color: rgb(187, 187, 187); border-radius: 24px; outline: none; padding: 3px 12px; margin: 2px 6px 12px 6px; box-sizing: border-box;\\">Following (0)</button></div></div><hr><div class=\\"follower-following-empty text-center text-muted\\">bob doesn't have any followers.</div></div><div class=\\"card card-user-sn hidden-xs hidden-sm\\"><h3 class=\\"text-center\\" style=\\"margin-top: 10px;\\">Similar Users</h3><hr><div class=\\"similar-users-empty text-center text-muted\\">Users with similar music tastes to bob will appear here.</div></div>"`;

0 comments on commit de6f3d4

Please sign in to comment.