Skip to content
This repository has been archived by the owner on Aug 16, 2019. It is now read-only.

Commit

Permalink
New media page design (#15)
Browse files Browse the repository at this point in the history
* Remove clamp - serious performance hit in Firefox and Edge

* Rough styles and layout

* Fix position

* Shouldn't be absolute

* Clean

* Use LoginLink component in top nav

* Clean up line endings

* Don't extend airbnb eslint config

* Unnecessary rule
  • Loading branch information
jrawsthorne committed May 20, 2018
1 parent 5d3b5e1 commit e9ea574
Show file tree
Hide file tree
Showing 34 changed files with 1,037 additions and 848 deletions.
11 changes: 3 additions & 8 deletions .eslintrc
@@ -1,5 +1,4 @@
{
"extends": "airbnb",
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 2016,
Expand All @@ -8,14 +7,10 @@
"env": {
"es6": true,
"browser": true,
"node": true,
"node": true
},
"rules": {
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
"jsx-a11y/anchor-is-valid": [ "error", {
"components": [ "Link" ],
"aspects": [ "invalidHref", "preferButton" ]
}],
"react/no-did-mount-set-state": 'off'
"jsx-a11y/anchor-is-valid": "off",
"react/no-did-mount-set-state": "off"
}
}
2 changes: 2 additions & 0 deletions api-server.js
Expand Up @@ -9,6 +9,7 @@ const passport = require('passport');
const posts = require('./src/apis/routes/posts');
const users = require('./src/apis/routes/users');
const ratings = require('./src/apis/routes/ratings');
const subscriptions = require('./src/apis/routes/subscriptions');

dotenv.config();
const app = express();
Expand All @@ -31,6 +32,7 @@ if (process.env.NODE_ENV === 'production') {

app.use(`${API_PREFIX}posts`, posts);
app.use(`${API_PREFIX}users`, users);
app.use(`${API_PREFIX}subscriptions`, subscriptions);
app.use(`${API_PREFIX}ratings`, ratings);

app.get('/*', (req, res) => res.status(401).send({ error: 'Route not found' }));
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -27,7 +27,6 @@
"babel-preset-stage-2": "^6.24.1",
"css-loader": "^0.28.9",
"eslint": "^4.19.1",
"eslint-config-airbnb": "^16.1.0",
"eslint-loader": "^2.0.0",
"eslint-plugin-import": "^2.11.0",
"eslint-plugin-jsx-a11y": "^6.0.3",
Expand Down Expand Up @@ -72,6 +71,7 @@
"prop-types": "^15.6.1",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-loadable": "^5.4.0",
"react-redux": "^5.0.6",
"react-router": "^4.2.0",
"react-router-config": "^1.0.0-beta.4",
Expand Down
16 changes: 14 additions & 2 deletions src/actions/authActions.js
@@ -1,13 +1,13 @@
import Cookie from 'js-cookie';
import axios from 'axios';
import steemConnectAPI from '../apis/steemConnectAPI';
import { LOGIN, LOGOUT } from './types';
import { LOGIN, LOGOUT, FETCH_USER_RATINGS, FETCH_USER_SUBSCRIPTIONS } from './types';

export const login = () => ({
type: LOGIN,
payload: axios.post(`${process.env.API_URL}/users/login`, { accessToken: Cookie.get('access_token') }).then((res) => {
axios.defaults.headers.common.Authorization = `Bearer ${res.data.token}`;
return res.data.user;
return res.data;
}).catch(() => {
Cookie.remove('access_token');
Cookie.remove('token');
Expand All @@ -27,4 +27,16 @@ export const logout = () => (dispatch) => {
});
};

export const fetchUserRatings = () => ({
type: FETCH_USER_RATINGS,
payload: axios.get(`${process.env.API_URL}/users/ratings`).then(res => res.data),
meta: { globalError: 'Error fetching ratings' },
});

export const fetchUserSubscriptions = () => ({
type: FETCH_USER_SUBSCRIPTIONS,
payload: axios.get(`${process.env.API_URL}/users/subscriptions`).then(res => res.data),
meta: { globalError: 'Error fetching subscriptions' },
});

export default login;
29 changes: 24 additions & 5 deletions src/actions/mediaActions.js
Expand Up @@ -9,19 +9,22 @@ import {
FETCH_EPISODE,
USER_RATE_CHANGE,
SUBSCRIBE_CHANGE,
FETCH_SIMILAR_MOVIES,
} from './types';

// fetch movie details and return object containing id, poster, backdrop, title, overview and year
export const fetchMovie = id => ({
type: FETCH_MOVIE,
payload: theMovieDBAPI.movieInfo(id)
payload: theMovieDBAPI.movieInfo({ id, append_to_response: 'credits' })
.then(movie => ({
id: movie.id,
poster_path: movie.poster_path,
backdrop_path: movie.backdrop_path,
title: movie.title,
overview: movie.overview,
year: movie.release_date && new Date(movie.release_date).getFullYear(),
actors: movie.credits.cast.slice(0, 3),
genres: movie.genres.slice(0, 3),
})),
meta: {
globalError: "Sorry, we couln't find that movie",
Expand All @@ -30,13 +33,23 @@ export const fetchMovie = id => ({
},
});

export const fetchSimilarMovies = id => ({
type: FETCH_SIMILAR_MOVIES,
payload: theMovieDBAPI.movieSimilar(id).then(res => _.shuffle(res.results).slice(0, 5)),
meta: {
globalError: 'Sorry, there was an error fetching similar movies',
id,
type: 'movies',
},
});

/*
fetch show details
return object containing id, poster, backdrop, title, overview, year and seasons
*/
export const fetchShow = id => ({
type: FETCH_SHOW,
payload: theMovieDBAPI.tvInfo(id)
payload: theMovieDBAPI.tvInfo({ id, append_to_response: 'credits' })
.then(show => ({
id: show.id,
poster_path: show.poster_path,
Expand All @@ -45,6 +58,8 @@ export const fetchShow = id => ({
overview: show.overview,
year: show.first_air_date && new Date(show.first_air_date).getFullYear(),
seasons: arrayToObject(show.seasons, 'season_number'),
actors: show.credits.cast.slice(0, 3),
genres: show.genres.slice(0, 3),
})),
meta: {
globalError: "Sorry, we couln't find that show",
Expand All @@ -62,7 +77,7 @@ export const fetchSeason = (id, seasonNum) => ({
type: FETCH_SEASON,
payload: theMovieDBAPI.tvInfo({
id,
append_to_response: `season/${seasonNum}`,
append_to_response: `season/${seasonNum},credits`,
}).then((show) => {
if (!show[`season/${seasonNum}`]) {
throw new Error('Show found, season not found');
Expand All @@ -73,6 +88,8 @@ export const fetchSeason = (id, seasonNum) => ({
backdrop_path: show.backdrop_path,
title: show.name,
overview: show.overview,
actors: show.credits.cast.slice(0, 3),
genres: show.genres.slice(0, 3),
seasons: {
...arrayToObject(show.seasons, 'season_number'),
[seasonNum]: {
Expand All @@ -98,7 +115,7 @@ export const fetchEpisode = (id, seasonNum, episodeNum) => ({
type: FETCH_EPISODE,
payload: theMovieDBAPI.tvInfo({
id,
append_to_response: `season/${seasonNum}`,
append_to_response: `season/${seasonNum},credits`,
}).then((show) => {
// if episode not found in episodes object throw error
if (!_.get(show, `[season/${seasonNum}].episodes`) || !_.get(show, `[season/${seasonNum}].episodes`).find(episode => episode.episode_number === parseInt(episodeNum, 10))) {
Expand All @@ -110,6 +127,8 @@ export const fetchEpisode = (id, seasonNum, episodeNum) => ({
backdrop_path: show.backdrop_path,
title: show.name,
overview: show.overview,
actors: show.credits.cast.slice(0, 3),
genres: show.genres.slice(0, 3),
seasons: {
...arrayToObject(show.seasons, 'season_number'),
[seasonNum]: {
Expand Down Expand Up @@ -155,7 +174,7 @@ export const userRateChange = (

export const subscribeChange = (type, tmdbid, subscribed) => ({
type: SUBSCRIBE_CHANGE,
payload: axios.post(`${process.env.API_URL}/users/subscriptions/change`, {
payload: axios.post(`${process.env.API_URL}/subscriptions/change`, {
type,
tmdbid,
subscribed,
Expand Down
13 changes: 13 additions & 0 deletions src/actions/types.js
Expand Up @@ -54,3 +54,16 @@ export const SUBSCRIBE_CHANGE = 'SUBSCRIBE_CHANGE';
export const SUBSCRIBE_CHANGE_PENDING = 'SUBSCRIBE_CHANGE_PENDING';
export const SUBSCRIBE_CHANGE_FULFILLED = 'SUBSCRIBE_CHANGE_FULFILLED';
export const SUBSCRIBE_CHANGE_REJECTED = 'SUBSCRIBE_CHANGE_REJECTED';

export const FETCH_USER_RATINGS = 'FETCH_USER_RATINGS';
export const FETCH_USER_RATINGS_FULFILLED = 'FETCH_USER_RATINGS_FULFILLED';
export const FETCH_USER_RATINGS_PENDING = 'FETCH_USER_RATINGS_PENDING';
export const FETCH_USER_RATINGS_REJECTED = 'FETCH_USER_RATINGS_REJECTED';

export const FETCH_USER_SUBSCRIPTIONS = 'FETCH_USER_SUBSCRIPTIONS';
export const FETCH_USER_SUBSCRIPTIONS_FULFILLED = 'FETCH_USER_SUBSCRIPTIONS_FULFILLED';
export const FETCH_USER_SUBSCRIPTIONS_PENDING = 'FETCH_USER_SUBSCRIPTIONS_PENDING';
export const FETCH_USER_SUBSCRIPTIONS_REJECTED = 'FETCH_USER_SUBSCRIPTIONS_REJECTED';

export const FETCH_SIMILAR_MOVIES = 'FETCH_SIMILAR_MOVIES';
export const FETCH_SIMILAR_MOVIES_FULFILLED = 'FETCH_SIMILAR_MOVIES_FULFILLED';
105 changes: 49 additions & 56 deletions src/apis/routes/ratings.js
@@ -1,81 +1,74 @@
const express = require('express');
const passport = require('passport');
const Rating = require('../models/Rating');
const User = require('../models/User');

const router = express.Router();

router.get('/', (req, res) => {
const {
mediaType, tmdbid, seasonNum, episodeNum,
} = req.query;
if (episodeNum && !seasonNum) {
return res.status(404).json('Ratings not found, please specify a season number as well');
}
return Rating.find({
mediaType, tmdbid, seasonNum, episodeNum,
}).populate('user', 'username')
.then(ratings => res.json(ratings));
});

router.post('/add', passport.authenticate('jwt', { session: false }), (req, res) => {
const {
user,
body: {
mediaType, tmdbid, seasonNum, episodeNum, value,
},
} = req;
// return error if score invalid
if (value > 5 || value < 0) {
return res.status(400).json({ error: 'Rating couldn\'t be added to the database' });
res.status(400).json({ error: 'Rating couldn\'t be added to the database' });
}
return Rating
.findOne({
user,
mediaType,
tmdbid,
seasonNum,
episodeNum,
})
.then((rating) => {
if (rating) {
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({}));
});
}
return Rating.findOneAndUpdate({
user,
mediaType,
tmdbid,
seasonNum,
episodeNum,
}, { score: value }, { new: true })
.then(newRating => res.json(newRating));
// find the rating
Rating.findOne({
user,
mediaType,
tmdbid,
seasonNum,
episodeNum,
}).then((rating) => {
if (rating) {
if (parseInt(value, 10) === 0) {
// remove rating if score is 0
rating.remove().then(() => {
// remove rating id from user
user.update({ $pull: { ratings: rating.id } }).then(() => {
// return empty object
res.json({});
});
});
} else {
// update the score for the rating
rating.update({ $set: { score: value } }).then(() => {
// return the rating with the new score
res.json({
mediaType: rating.mediaType,
tmdbid: rating.tmdbid,
score: parseInt(value, 10),
seasonNum: rating.seasonNum || undefined,
episodeNum: rating.episodeNum || undefined,
});
});
}

return new Rating({
} else {
// create a new rating
new Rating({
user,
mediaType,
tmdbid,
seasonNum,
episodeNum,
score: value,
})
.save()
.then(newRating =>
User.update({ _id: user.id }, { $push: { ratings: { _id: newRating.id } } })
.then(() => res.json(newRating)));
});
}).save().then(newRating =>
// add the rating id to the user
user.update({ $push: { ratings: { _id: newRating.id } } }).then(() => {
// return the new rating
res.json({
mediaType: newRating.mediaType,
tmdbid: newRating.tmdbid,
score: newRating.score,
seasonNum: newRating.seasonNum || undefined,
episodeNum: newRating.episodeNum || undefined,
});
}));
}
});
});

module.exports = router;

0 comments on commit e9ea574

Please sign in to comment.