Development Update #2: Ratings, Subscriptions and Profiles
Repository
https://github.com/jrawsthorne/review.app
New Features
Better filters for pages - store list of posts matching filter in redux storePost formatting - youtube/dtube/more complex markdown/htmlUser profile pagesAllow all users to give star ratingSubscribe to certain showSubscribed page showing all posts from subscribed shows/movies
#1 User profile pages GitHub Link
You can visit a user's profile page by going to /@username like with most steem apps. The profile page shows the name, username, website, location and bio at the top with the avatar to the left and cover in the background. Below that is posts by that user.
#2 Star ratings
I decided that a user should be able to rate any media item on the site so I needed to create a place for ratings in the database.
This is the schema (GitHub Link)
const schema = new Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: 'users',
required: true,
},
score: {
type: Number,
required: true,
},
mediaType: {
type: String,
required: true,
},
tmdbid: {
type: Number,
required: true,
},
seasonNum: {
type: Number,
},
episodeNum: {
type: Number,
},
},
{
timestamps: true,
},
);
Once logged in a user can go to any post and with the rest of the metadata at the top there are 5 stars. Clicking one will immediately add this rating to your account. In the future when there are sufficient ratings I hope to display an average as well. Clicking the same number of stars again will remove the rating so the minimum you can give is 1 star.
When a user sets the score to 0 it is completely deleted from the database. GitHub Link
if (parseInt(value, 10) === 0) {
return Rating
.findOne({
user,
mediaType,
tmdbid,
seasonNum,
episodeNum,
})
.remove()
.then(() => {
User.update({ _id: user.id }, { $pull: { ratings: rating.id } })
.then(() => res.json({}));
});
}
#3 Subscriptions
A user is also able to subscribe to certain shows or movies if they want to produce a feed with just posts from those shows/movies. I decided to implement this and will provide it as well as a general steem feed of content from users you follow.
This is the schema (GitHub Link)
const schema = new Schema(
{
user: {
type: Schema.Types.ObjectId,
ref: 'users',
required: true,
},
tmdbid: {
type: Number,
required: true,
},
type: {
type: String,
required: true,
},
},
);
To display all the posts for a subscription I loop through each one and find all the posts matching that criteria and add it to an array. (GithHub Link)
router.get('/subscriptions', passport.authenticate('jwt', { session: false }), (req, res) => {
const { user } = req;
let count = 0;
Subscription.find({ user })
.then((subscriptions) => {
Promise.all(subscriptions.map(subscription =>
Post.count({ type: subscription.type, tmdbid: subscription.tmdbid }).then(c =>
Post.find({ type: subscription.type, tmdbid: subscription.tmdbid })
.then((posts) => { count += c; return posts; }))))
.then(posts => res.json({
count,
results: orderBy(flatten(posts), 'createdAt', 'desc'),
}));
})
.catch(() => res.status(404).json({ error: 'Error fetching subscriptions' }));
});
#4 JSON web token
To facilitate the previous two new features I added a new sign in flow so that I don't have to rely on steem authentication for every protected action. Having to access the steem api for every rating and subscription was very slow. As those two things don't rely on the steem blockchain it was unnecessary to authenticate using a steemconnect token so I now store a JSON web token with the users details in it. (GitHub Link)
router.post('/login', (req, res) => {
const { accessToken } = req.body;
if (!accessToken) res.status(400).json({ error: 'Not authenticated' });
steemConnectAPI.setAccessToken(accessToken);
steemConnectAPI.me()
.then((steemUser) => {
User.findOne({ username: steemUser.name }).populate({ path: 'ratings', select: 'score mediaType tmdbid seasonNum episodeNum' }).populate('subscriptions', 'tmdbid type')
.then((user) => {
if (user) {
const token = jwt.sign({
id: user.id,
username: user.username,
}, process.env.JWT_SECRET, { expiresIn: '1h' });
res.json({
user: {
...steemUser,
account: {
...steemUser.account,
ratings: {
scores: user.ratings,
},
subscriptions: {
items: user.subscriptions,
},
},
},
token,
});
} else {
new User({ username: steemUser.name }).save().then((newUser) => {
const token = jwt.sign({
id: newUser.id,
username: newUser.username,
}, process.env.JWT_SECRET, { expiresIn: '1h' });
res.json({
user: steemUser,
token,
});
});
}
});
})
.catch(() => res.status(400).json({ error: 'Not authenticated' }));
});
#5 Updated styling
The interface for switching between episodes and seasons has been improved with a clickable tooltip. Although this doesn't provide as much information for the user, it saves a lot of space that was wasted before in my opinion. (GitHub Link)
{props.seasons &&
<div className="MediaHeader__info__selectors">
{props.seasons &&
<Popover
onVisibleChange={props.handleSeasonVisibleChange}
visible={props.showSeasons}
placement="bottom"
content={Object.values(props.seasons).map(season =>
(
<p
onClick={() => handleSeasonClick(season.season_number)}
className="Filter__option"
key={`season-${season.season_number}`}
>{season.name}
</p>
))}
trigger="click"
>
<span className="Filter__dropdown" style={{ marginLeft: 0 }}>
Seasons <Icon type="down" style={{ fontSize: 15 }} />
</span>
</Popover>
}
{props.episodes &&
<Popover
onVisibleChange={props.handleEpisodeVisibleChange}
visible={props.showEpisodes}
placement="bottom"
content={Object.values(props.episodes).map(episode =>
(
<p
onClick={() => handleEpisodeClick(episode.episode_number)}
className="Filter__option"
key={`season-${episode.episode_number}`}
>{episode.name}
</p>
))}
trigger="click"
>
<span className="Filter__dropdown">
Episodes <Icon type="down" style={{ fontSize: 15 }} />
</span>
</Popover>
}
</div>
}
Roadmap
- Ability to actually write new posts
- Store all database info in JSON metadata of a post as backup
- User actions (like, comment)
Proof of Work Done https://github.com/jrawsthorne
Leave Development Update #2: Ratings, Subscriptions and Profiles to:
Read more #utopian-io posts
Best Posts From Jake Rawsthorne
We have not curated any of jrawsthorne's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.
More Posts From Jake Rawsthorne
- Introducing a new STEEM frontend: LiveSteem
- Would you use a frontend that functioned like a live chat?
- Something I've been testing out recently
- Querying Hivemind with GraphQL
- Busy 2.5.1 Bug: Duplicate comment when showing more replies from a nested comment page
- Busy 2.5.1 Bug: Edit post button doesn't show the post data in the editor initially
- Development Update #5: Comments, Loading States and Refresh Feeds
- Busy.org Bug: Post with no json_metadata crashes the whole page
- Development Update #4: Write New Post, Trending Posts and Upvote Post
- Test
- Brooklyn Nine-Nine review test
- Deadpool 2 test
- Deadpool test
- test
- Game of thrones test review
- Development Update #3: Updated Design, Recommended, Actors Page and New Post Page
- Carbon - Create and share beautiful images of your source code
- Busy.org: Going back in history takes you to the same post page if you got there from a modal
- Busy.org: Reblogged username disappears when you like a post
- Development Update #2: Ratings, Subscriptions and Profiles