diff --git a/frontend/js/actions/admins.js b/frontend/js/actions/admins.js index 9beb65b..33e2a15 100644 --- a/frontend/js/actions/admins.js +++ b/frontend/js/actions/admins.js @@ -1,42 +1,29 @@ -import { configureAxios, request } from "../requests" +import { configureAxios, request } from "../requests"; export function getUsers() { - return request( - "ADMIN_LIST_USERS", - configureAxios().get("/admins/users") - ) + return request("ADMIN_LIST_USERS", configureAxios().get("/admins/users")); } export function getStats() { - return request( - "ADMIN_GET_STATS", - configureAxios().get("/admins/stats") - ) + return request("ADMIN_GET_STATS", configureAxios().get("/admins/stats")); } export function getAdminModules() { - return request( - "ADMIN_GET_MODULES", - configureAxios().get("/admins/modules") - ) + return request("ADMIN_GET_MODULES", configureAxios().get("/admins/modules")); } export function updateUser(data) { return request( "ADMIN_UPDATE_USER", configureAxios().post("/admins/users", data), - [ - () => getUsers(), - ] - ) + [() => getUsers()] + ); } export function deleteUser(username) { return request( "ADMIN_DELETE_USER", - configureAxios().delete("/admins/users/"+ username), - [ - () => getUsers(), - ] - ) + configureAxios().delete("/admins/users/" + username), + [() => getUsers()] + ); } diff --git a/frontend/js/actions/alerts.js b/frontend/js/actions/alerts.js index d4ae8b0..3f3b8fb 100644 --- a/frontend/js/actions/alerts.js +++ b/frontend/js/actions/alerts.js @@ -2,22 +2,22 @@ export function addAlertError(message) { return { type: "ADD_ALERT_ERROR", payload: { - message, + message } - } + }; } export function addAlertOk(message) { return { type: "ADD_ALERT_OK", payload: { - message, + message } - } + }; } export function dismissAlert() { return { - type: "DISMISS_ALERT", - } + type: "DISMISS_ALERT" + }; } diff --git a/frontend/js/actions/movies.js b/frontend/js/actions/movies.js index 6fab182..0c182b4 100644 --- a/frontend/js/actions/movies.js +++ b/frontend/js/actions/movies.js @@ -1,40 +1,40 @@ -import { configureAxios, request } from "../requests" +import { configureAxios, request } from "../requests"; -import { addAlertOk } from "./alerts" -import { sendNotification } from "./notifications" +import { addAlertOk } from "./alerts"; +import { sendNotification } from "./notifications"; export function updateLastMovieFetchUrl(url) { return { type: "UPDATE_LAST_MOVIE_FETCH_URL", payload: { - url: url, - }, - } + url: url + } + }; } export function selectMovie(imdbId) { return { type: "SELECT_MOVIE", payload: { - imdbId, - }, - } + imdbId + } + }; } export function updateFilter(filter) { return { type: "MOVIE_UPDATE_FILTER", payload: { - filter, - }, - } + filter + } + }; } export function getMovieExploreOptions() { return request( "MOVIE_GET_EXPLORE_OPTIONS", configureAxios().get("/movies/explore/options") - ) + ); } export function getMovieDetails(imdbId) { @@ -43,27 +43,23 @@ export function getMovieDetails(imdbId) { configureAxios().post(`/movies/${imdbId}/refresh`), null, { - imdbId, + imdbId } - ) + ); } export function deleteMovie(imdbId, lastFetchUrl) { - return request( - "MOVIE_DELETE", - configureAxios().delete(`/movies/${imdbId}`), - [ - fetchMovies(lastFetchUrl), - addAlertOk("Movie deleted"), - ], - ) + return request("MOVIE_DELETE", configureAxios().delete(`/movies/${imdbId}`), [ + fetchMovies(lastFetchUrl), + addAlertOk("Movie deleted") + ]); } export function movieWishlistToggle(imdbId, currentState) { if (currentState == true) { - return deleteMovieFromWishlist(imdbId) + return deleteMovieFromWishlist(imdbId); } else { - return addMovieToWishlist(imdbId) + return addMovieToWishlist(imdbId); } } @@ -71,20 +67,16 @@ export function addMovieToWishlist(imdbId) { return request( "MOVIE_ADD_TO_WISHLIST", configureAxios().post(`/wishlist/movies/${imdbId}`), - [ - updateMovieWishlistStore(imdbId, true), - ], - ) + [updateMovieWishlistStore(imdbId, true)] + ); } export function deleteMovieFromWishlist(imdbId) { return request( "MOVIE_DELETE_FROM_WISHLIST", configureAxios().delete(`/wishlist/movies/${imdbId}`), - [ - updateMovieWishlistStore(imdbId, false), - ], - ) + [updateMovieWishlistStore(imdbId, false)] + ); } export function updateMovieWishlistStore(imdbId, wishlisted) { @@ -92,29 +84,27 @@ export function updateMovieWishlistStore(imdbId, wishlisted) { type: "MOVIE_UPDATE_STORE_WISHLIST", payload: { imdbId, - wishlisted, + wishlisted } - } + }; } export function fetchMovies(url) { - return request( - "MOVIE_LIST_FETCH", - configureAxios().get(url), - [ - updateLastMovieFetchUrl(url), - ] - ) + return request("MOVIE_LIST_FETCH", configureAxios().get(url), [ + updateLastMovieFetchUrl(url) + ]); } -export const newMovieEvent = (data) => { - return (dispatch) => { - dispatch(sendNotification({ - icon: "film", - autohide: true, - delay: 10000, - title: `${data.title} added to the library`, - imageUrl: data.thumb, - })); - } -} +export const newMovieEvent = data => { + return dispatch => { + dispatch( + sendNotification({ + icon: "film", + autohide: true, + delay: 10000, + title: `${data.title} added to the library`, + imageUrl: data.thumb + }) + ); + }; +}; diff --git a/frontend/js/actions/notifications.js b/frontend/js/actions/notifications.js index 6e060ae..6f4347e 100644 --- a/frontend/js/actions/notifications.js +++ b/frontend/js/actions/notifications.js @@ -1,9 +1,9 @@ -export const sendNotification = (data) => ({ +export const sendNotification = data => ({ type: "ADD_NOTIFICATION", - payload: data, -}) + payload: data +}); -export const removeNotification = (id) => ({ +export const removeNotification = id => ({ type: "REMOVE_NOTIFICATION", - payload: { id }, -}) + payload: { id } +}); diff --git a/frontend/js/actions/polochon.js b/frontend/js/actions/polochon.js index 177868e..3be9ca8 100644 --- a/frontend/js/actions/polochon.js +++ b/frontend/js/actions/polochon.js @@ -1,50 +1,38 @@ -import { configureAxios, request } from "../requests" +import { configureAxios, request } from "../requests"; -import { getUserInfos } from "./users" +import { getUserInfos } from "./users"; -export const getPolochons = () => request( - "PUBLIC_POLOCHON_LIST_FETCH", - configureAxios().get("/polochons"), -) +export const getPolochons = () => + request("PUBLIC_POLOCHON_LIST_FETCH", configureAxios().get("/polochons")); -export const getManagedPolochons = () => request( - "MANAGED_POLOCHON_LIST_FETCH", - configureAxios().get("/users/polochons"), -) +export const getManagedPolochons = () => + request( + "MANAGED_POLOCHON_LIST_FETCH", + configureAxios().get("/users/polochons") + ); -export const addPolochon = (params) => request( - "ADD_POLOCHON", - configureAxios().post("/polochons", params), - [ +export const addPolochon = params => + request("ADD_POLOCHON", configureAxios().post("/polochons", params), [ () => getPolochons(), - () => getManagedPolochons(), - ], -) + () => getManagedPolochons() + ]); -export const updatePolochon = ({ id, ...params }) => request( - "UPDATE_POLOCHON", - configureAxios().post(`/polochons/${id}`, params), - [ - () => getPolochons(), - () => getManagedPolochons(), - ], -) +export const updatePolochon = ({ id, ...params }) => + request( + "UPDATE_POLOCHON", + configureAxios().post(`/polochons/${id}`, params), + [() => getPolochons(), () => getManagedPolochons()] + ); -export const deletePolochon = (id) => request( - "DELETE_POLOCHON", - configureAxios().delete(`/polochons/${id}`), - [ +export const deletePolochon = id => + request("DELETE_POLOCHON", configureAxios().delete(`/polochons/${id}`), [ () => getPolochons(), - () => getManagedPolochons(), - ], -) + () => getManagedPolochons() + ]); -export const editPolochonUser = ({ polochonId, id, ...params }) => request( - "EDIT_POLOCHON_USER", - configureAxios().post(`/polochons/${polochonId}/users/${id}`, params), - [ - () => getPolochons(), - () => getManagedPolochons(), - () => getUserInfos(), - ], -) +export const editPolochonUser = ({ polochonId, id, ...params }) => + request( + "EDIT_POLOCHON_USER", + configureAxios().post(`/polochons/${polochonId}/users/${id}`, params), + [() => getPolochons(), () => getManagedPolochons(), () => getUserInfos()] + ); diff --git a/frontend/js/actions/shows.js b/frontend/js/actions/shows.js index 98b4add..6f0761e 100644 --- a/frontend/js/actions/shows.js +++ b/frontend/js/actions/shows.js @@ -1,16 +1,12 @@ -import { configureAxios, request } from "../requests" +import { configureAxios, request } from "../requests"; -import { prettyEpisodeName } from "../utils" -import { sendNotification } from "./notifications" +import { prettyEpisodeName } from "../utils"; +import { sendNotification } from "./notifications"; export function fetchShows(url) { - return request( - "SHOW_LIST_FETCH", - configureAxios().get(url), - [ - updateLastShowsFetchUrl(url), - ] - ) + return request("SHOW_LIST_FETCH", configureAxios().get(url), [ + updateLastShowsFetchUrl(url) + ]); } export function getShowDetails(imdbId) { @@ -19,21 +15,22 @@ export function getShowDetails(imdbId) { configureAxios().post(`/shows/${imdbId}/refresh`), null, { imdbId } - ) + ); } - export function getEpisodeDetails(imdbId, season, episode) { return request( "EPISODE_GET_DETAILS", - configureAxios().post(`/shows/${imdbId}/seasons/${season}/episodes/${episode}`), + configureAxios().post( + `/shows/${imdbId}/seasons/${season}/episodes/${episode}` + ), null, { imdbId, season, - episode, + episode } - ) + ); } export function fetchShowDetails(imdbId) { @@ -42,7 +39,7 @@ export function fetchShowDetails(imdbId) { configureAxios().get(`/shows/${imdbId}`), null, { imdbId } - ) + ); } export function addShowToWishlist(imdbId, season = null, episode = null) { @@ -50,25 +47,26 @@ export function addShowToWishlist(imdbId, season = null, episode = null) { "SHOW_ADD_TO_WISHLIST", configureAxios().post(`/wishlist/shows/${imdbId}`, { season: season, - episode: episode, + episode: episode }), - [ - updateShowWishlistStore(imdbId, true, season, episode), - ], - ) + [updateShowWishlistStore(imdbId, true, season, episode)] + ); } export function deleteShowFromWishlist(imdbId) { return request( "SHOW_DELETE_FROM_WISHLIST", configureAxios().delete(`/wishlist/shows/${imdbId}`), - [ - updateShowWishlistStore(imdbId, false), - ], - ) + [updateShowWishlistStore(imdbId, false)] + ); } -export function showWishlistToggle(currentState, imdbId, season = 0, episode = 0) { +export function showWishlistToggle( + currentState, + imdbId, + season = 0, + episode = 0 +) { if (currentState === true) { return deleteShowFromWishlist(imdbId); } else { @@ -76,60 +74,70 @@ export function showWishlistToggle(currentState, imdbId, season = 0, episode = 0 } } -export function updateShowWishlistStore(imdbId, wishlisted, season = null, episode = null) { +export function updateShowWishlistStore( + imdbId, + wishlisted, + season = null, + episode = null +) { return { type: "SHOW_UPDATE_STORE_WISHLIST", payload: { imdbId, season, - episode, + episode } - } + }; } export function getShowExploreOptions() { return request( "SHOW_GET_EXPLORE_OPTIONS", configureAxios().get("/shows/explore/options") - ) + ); } export function selectShow(imdbId) { return { type: "SELECT_SHOW", payload: { - imdbId, + imdbId } - } + }; } export function updateFilter(filter) { return { type: "SHOWS_UPDATE_FILTER", payload: { - filter, - }, - } + filter + } + }; } - export function updateLastShowsFetchUrl(url) { return { type: "UPDATE_LAST_SHOWS_FETCH_URL", payload: { - url: url, - }, - } + url: url + } + }; } -export const newEpisodeEvent = (data) => { - return (dispatch) => { - dispatch(sendNotification({ - icon: "video-camera", - autohide: true, - delay: 10000, - title: `${prettyEpisodeName(data.show_title, data.season, data.episode)} added to the library`, - imageUrl: `img/shows/${data.show_imdb_id}-poster.jpg`, - })); - } -} +export const newEpisodeEvent = data => { + return dispatch => { + dispatch( + sendNotification({ + icon: "video-camera", + autohide: true, + delay: 10000, + title: `${prettyEpisodeName( + data.show_title, + data.season, + data.episode + )} added to the library`, + imageUrl: `img/shows/${data.show_imdb_id}-poster.jpg` + }) + ); + }; +}; diff --git a/frontend/js/actions/subtitles.js b/frontend/js/actions/subtitles.js index 404e42c..7f2e92f 100644 --- a/frontend/js/actions/subtitles.js +++ b/frontend/js/actions/subtitles.js @@ -1,13 +1,13 @@ -import { configureAxios, request } from "../requests" +import { configureAxios, request } from "../requests"; -export const searchMovieSubtitles = (imdbId) => { +export const searchMovieSubtitles = imdbId => { return request( "MOVIE_SUBTITLES_UPDATE", configureAxios().post(`/movies/${imdbId}/subtitles/refresh`), null, - { imdbId: imdbId }, - ) -} + { imdbId: imdbId } + ); +}; export const searchEpisodeSubtitles = (imdbId, season, episode) => { const url = `/shows/${imdbId}/seasons/${season}/episodes/${episode}`; @@ -18,7 +18,7 @@ export const searchEpisodeSubtitles = (imdbId, season, episode) => { { imdbId: imdbId, season: season, - episode: episode, - }, + episode: episode + } ); -} +}; diff --git a/frontend/js/actions/torrents.js b/frontend/js/actions/torrents.js index 69e6b2c..ecac6e9 100644 --- a/frontend/js/actions/torrents.js +++ b/frontend/js/actions/torrents.js @@ -1,41 +1,29 @@ -import { configureAxios, request } from "../requests" +import { configureAxios, request } from "../requests"; -import { addAlertOk } from "./alerts" +import { addAlertOk } from "./alerts"; export function addTorrent(url) { return request( "ADD_TORRENT", configureAxios().post("/torrents", { - url: url, + url: url }), - [ - addAlertOk("Torrent added"), - ], - ) + [addAlertOk("Torrent added")] + ); } export function removeTorrent(id) { - return request( - "REMOVE_TORRENT", - configureAxios().delete(`/torrents/${id}`), - [ - () => fetchTorrents(), - ] - ) + return request("REMOVE_TORRENT", configureAxios().delete(`/torrents/${id}`), [ + () => fetchTorrents() + ]); } export function fetchTorrents() { - return request( - "TORRENTS_FETCH", - configureAxios().get("/torrents") - ) + return request("TORRENTS_FETCH", configureAxios().get("/torrents")); } export function searchTorrents(url) { - return request( - "TORRENTS_SEARCH", - configureAxios().get(url) - ) + return request("TORRENTS_SEARCH", configureAxios().get(url)); } export function setFetchedTorrents(torrents) { @@ -43,8 +31,8 @@ export function setFetchedTorrents(torrents) { type: "TORRENTS_FETCH_FULFILLED", payload: { response: { - data : torrents, - }, - }, - } + data: torrents + } + } + }; } diff --git a/frontend/js/actions/users.js b/frontend/js/actions/users.js index bce02b6..9bb312a 100644 --- a/frontend/js/actions/users.js +++ b/frontend/js/actions/users.js @@ -1,40 +1,31 @@ -import { configureAxios, request } from "../requests" +import { configureAxios, request } from "../requests"; -import { addAlertOk, dismissAlert } from "./alerts" +import { addAlertOk, dismissAlert } from "./alerts"; -import { getManagedPolochons } from "./polochon" +import { getManagedPolochons } from "./polochon"; export function userLogout() { return { - type: "USER_LOGOUT", - } + type: "USER_LOGOUT" + }; } export function loginUser(username, password) { return request( "USER_LOGIN", - configureAxios().post( - "/users/login", - { - username: username.trim(), - password: password, - }, - ), - [ - () => dismissAlert(), - ] - ) + configureAxios().post("/users/login", { + username: username.trim(), + password: password + }), + [() => dismissAlert()] + ); } export function updateUser(config) { - return request( - "USER_UPDATE", - configureAxios().post("/users/edit", config), - [ - addAlertOk("User updated"), - () => getManagedPolochons(), - ], - ) + return request("USER_UPDATE", configureAxios().post("/users/edit", config), [ + addAlertOk("User updated"), + () => getManagedPolochons() + ]); } export function userSignUp(config) { @@ -44,48 +35,39 @@ export function userSignUp(config) { return request( "USER_SIGNUP", - configureAxios().post("/users/signup", config), [ - () => loginUser(config.username, config.password), - ], - ) + configureAxios().post("/users/signup", config), + [() => loginUser(config.username, config.password)] + ); } export function getUserInfos() { - return request( - "GET_USER", - configureAxios().get("/users/details") - ) + return request("GET_USER", configureAxios().get("/users/details")); } export function setUserToken(token) { return { type: "USER_SET_TOKEN", payload: { - token: token, - }, - } + token: token + } + }; } export function getUserTokens() { - return request( - "GET_USER_TOKENS", - configureAxios().get("/users/tokens") - ) + return request("GET_USER_TOKENS", configureAxios().get("/users/tokens")); } export function deleteUserToken(token) { return request( "DELETE_USER_TOKEN", configureAxios().delete(`/users/tokens/${token}`), - [ - () => getUserTokens(), - ] - ) + [() => getUserTokens()] + ); } export function getUserModules() { return request( "GET_USER_MODULES", configureAxios().get("/users/modules/status") - ) + ); } diff --git a/frontend/js/app.js b/frontend/js/app.js index 495b560..c7638c8 100644 --- a/frontend/js/app.js +++ b/frontend/js/app.js @@ -1,47 +1,47 @@ // Import default image -import "../img/noimage.png" +import "../img/noimage.png"; // Import favicon settings -import "../img/favicon-16x16.png" -import "../img/favicon-32x32.png" -import "../img/favicon.ico" -import "../img/safari-pinned-tab.svg" +import "../img/favicon-16x16.png"; +import "../img/favicon-32x32.png"; +import "../img/favicon.ico"; +import "../img/safari-pinned-tab.svg"; // Styles -import "../scss/app.scss" +import "../scss/app.scss"; // React -import React from "react" -import ReactDOM from "react-dom" -import { Provider } from "react-redux" -import { Router, Route, Switch, Redirect } from "react-router-dom" -import Container from "react-bootstrap/Container" +import React from "react"; +import ReactDOM from "react-dom"; +import { Provider } from "react-redux"; +import { Router, Route, Switch, Redirect } from "react-router-dom"; +import Container from "react-bootstrap/Container"; // Auth -import { ProtectedRoute, AdminRoute } from "./auth" +import { ProtectedRoute, AdminRoute } from "./auth"; // Store -import store, { history } from "./store" +import store, { history } from "./store"; // Components -import { AdminPanel } from "./components/admins/panel" -import { Notifications } from "./components/notifications/notifications" -import Alert from "./components/alerts/alert" -import MovieList from "./components/movies/list" -import MoviesRoute from "./components/movies/route" -import NavBar from "./components/navbar" -import WsHandler from "./components/websocket" -import { ShowDetails } from "./components/shows/details" -import ShowList from "./components/shows/list" -import ShowsRoute from "./components/shows/route" -import TorrentList from "./components/torrents/list" -import TorrentSearch from "./components/torrents/search" -import UserActivation from "./components/users/activation" -import UserLoginForm from "./components/users/login" -import UserLogout from "./components/users/logout" -import UserProfile from "./components/users/profile" -import UserSignUp from "./components/users/signup" -import UserTokens from "./components/users/tokens" +import { AdminPanel } from "./components/admins/panel"; +import { Notifications } from "./components/notifications/notifications"; +import Alert from "./components/alerts/alert"; +import MovieList from "./components/movies/list"; +import MoviesRoute from "./components/movies/route"; +import NavBar from "./components/navbar"; +import WsHandler from "./components/websocket"; +import { ShowDetails } from "./components/shows/details"; +import ShowList from "./components/shows/list"; +import ShowsRoute from "./components/shows/route"; +import TorrentList from "./components/torrents/list"; +import TorrentSearch from "./components/torrents/search"; +import UserActivation from "./components/users/activation"; +import UserLoginForm from "./components/users/login"; +import UserLogout from "./components/users/logout"; +import UserProfile from "./components/users/profile"; +import UserSignUp from "./components/users/signup"; +import UserTokens from "./components/users/tokens"; const App = () => (
@@ -56,25 +56,43 @@ const App = () => ( - + - - + + - - - - - }/> + + + } />
); -ReactDOM.render(( +ReactDOM.render( @@ -85,5 +103,6 @@ ReactDOM.render(( - -),document.getElementById("app")); + , + document.getElementById("app") +); diff --git a/frontend/js/auth.js b/frontend/js/auth.js index 80aea36..d97588c 100644 --- a/frontend/js/auth.js +++ b/frontend/js/auth.js @@ -1,8 +1,8 @@ -import React from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import { Route, Redirect } from "react-router-dom" -import { setUserToken } from "./actions/users" +import React from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { Route, Redirect } from "react-router-dom"; +import { setUserToken } from "./actions/users"; const protectedRoute = ({ component: Component, @@ -22,59 +22,64 @@ const protectedRoute = ({ if (!isTokenSet) { setUserToken(token); } - return true + return true; } - return false - } + return false; + }; return ( - { - if (isAuthenticated()) { - if (isActivated) { - return + { + if (isAuthenticated()) { + if (isActivated) { + return ; + } else { + return ; + } } else { - return + return ; } - } else { - return - } - }} /> - ) -} + }} + /> + ); +}; protectedRoute.propTypes = { component: PropTypes.func, isLogged: PropTypes.bool.isRequired, isActivated: PropTypes.bool.isRequired, isTokenSet: PropTypes.bool.isRequired, - setUserToken: PropTypes.func.isRequired, + setUserToken: PropTypes.func.isRequired }; -export const ProtectedRoute = connect((state) => ({ - isLogged: state.userStore.get("isLogged"), - isAdmin: state.userStore.get("isLogged"), - isActivated: state.userStore.get("isActivated"), - isTokenSet: state.userStore.get("isTokenSet"), -}), { setUserToken })(protectedRoute); +export const ProtectedRoute = connect( + state => ({ + isLogged: state.userStore.get("isLogged"), + isAdmin: state.userStore.get("isLogged"), + isActivated: state.userStore.get("isActivated"), + isTokenSet: state.userStore.get("isTokenSet") + }), + { setUserToken } +)(protectedRoute); -const adminRoute = ({ - component: Component, - isAdmin, - ...otherProps -}) => { +const adminRoute = ({ component: Component, isAdmin, ...otherProps }) => { return ( - { - if (isAdmin) { - return - } else { - return - } - }} /> - ) -} + { + if (isAdmin) { + return ; + } else { + return ; + } + }} + /> + ); +}; adminRoute.propTypes = { component: PropTypes.func, - isAdmin: PropTypes.bool.isRequired, + isAdmin: PropTypes.bool.isRequired }; -export const AdminRoute = connect((state) => ({ - isAdmin: state.userStore.get("isLogged"), +export const AdminRoute = connect(state => ({ + isAdmin: state.userStore.get("isLogged") }))(adminRoute); diff --git a/frontend/js/components/admins/modules.js b/frontend/js/components/admins/modules.js index 6b99cb8..7c41604 100644 --- a/frontend/js/components/admins/modules.js +++ b/frontend/js/components/admins/modules.js @@ -1,28 +1,28 @@ -import React, { useEffect } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import { getAdminModules} from "../../actions/admins" +import React, { useEffect } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { getAdminModules } from "../../actions/admins"; -import Modules from "../modules/modules" +import Modules from "../modules/modules"; const AdminModulesConnected = ({ modules, loading, getAdminModules }) => { useEffect(() => { getAdminModules(); - }, [getAdminModules]) + }, [getAdminModules]); - return ( - - ) -} + return ; +}; AdminModulesConnected.propTypes = { modules: PropTypes.object, loading: PropTypes.bool, - getAdminModules: PropTypes.func.isRequired, + getAdminModules: PropTypes.func.isRequired }; const mapStateToProps = state => ({ loading: state.adminStore.get("fetchingModules"), - modules: state.adminStore.get("modules"), + modules: state.adminStore.get("modules") }); -export const AdminModules = connect(mapStateToProps, {getAdminModules})(AdminModulesConnected); +export const AdminModules = connect(mapStateToProps, { getAdminModules })( + AdminModulesConnected +); diff --git a/frontend/js/components/admins/panel.js b/frontend/js/components/admins/panel.js index 874f082..8e7a309 100644 --- a/frontend/js/components/admins/panel.js +++ b/frontend/js/components/admins/panel.js @@ -1,8 +1,8 @@ -import React from "react" +import React from "react"; -import { UserList } from "./userList" -import { Stats } from "./stats" -import { AdminModules } from "./modules" +import { UserList } from "./userList"; +import { Stats } from "./stats"; +import { AdminModules } from "./modules"; export const AdminPanel = () => ( @@ -10,4 +10,4 @@ export const AdminPanel = () => ( -) +); diff --git a/frontend/js/components/admins/stat.js b/frontend/js/components/admins/stat.js index f4164a2..d1aa61d 100644 --- a/frontend/js/components/admins/stat.js +++ b/frontend/js/components/admins/stat.js @@ -1,7 +1,7 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; -import { TorrentsStat } from "./torrentsStat" +import { TorrentsStat } from "./torrentsStat"; export const Stat = ({ name, count, torrentCount, torrentCountById }) => (
@@ -9,7 +9,9 @@ export const Stat = ({ name, count, torrentCount, torrentCountById }) => (

{name} - {count} + + {count} +

@@ -21,10 +23,10 @@ export const Stat = ({ name, count, torrentCount, torrentCountById }) => (
-) +); Stat.propTypes = { name: PropTypes.string, count: PropTypes.number, torrentCount: PropTypes.number, - torrentCountById: PropTypes.number, + torrentCountById: PropTypes.number }; diff --git a/frontend/js/components/admins/stats.js b/frontend/js/components/admins/stats.js index fe8b132..a0a467c 100644 --- a/frontend/js/components/admins/stats.js +++ b/frontend/js/components/admins/stats.js @@ -1,15 +1,15 @@ -import React, { useEffect } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" +import React, { useEffect } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; -import { Stat } from "./stat" +import { Stat } from "./stat"; -import { getStats } from "../../actions/admins" +import { getStats } from "../../actions/admins"; const StatsConnected = ({ stats, getStats }) => { useEffect(() => { getStats(); - }, [getStats]) + }, [getStats]); return (
@@ -32,15 +32,15 @@ const StatsConnected = ({ stats, getStats }) => { torrentCountById={stats.get("episodes_torrents_count_by_id")} />
- ) -} + ); +}; StatsConnected.propTypes = { stats: PropTypes.object, - getStats: PropTypes.func, -} + getStats: PropTypes.func +}; const mapStateToProps = state => ({ - stats: state.adminStore.get("stats"), + stats: state.adminStore.get("stats") }); -export const Stats = connect(mapStateToProps, {getStats})(StatsConnected); +export const Stats = connect(mapStateToProps, { getStats })(StatsConnected); diff --git a/frontend/js/components/admins/torrentsStat.js b/frontend/js/components/admins/torrentsStat.js index fa8abbe..791a0b3 100644 --- a/frontend/js/components/admins/torrentsStat.js +++ b/frontend/js/components/admins/torrentsStat.js @@ -1,9 +1,9 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; export const TorrentsStat = ({ count, torrentCount, torrentCountById }) => { if (torrentCount === undefined) { - return (No torrents); + return No torrents; } const percentage = Math.floor((torrentCountById * 100) / count); @@ -13,9 +13,9 @@ export const TorrentsStat = ({ count, torrentCount, torrentCountById }) => {   - {torrentCount} total ); -} +}; TorrentsStat.propTypes = { count: PropTypes.number, torrentCount: PropTypes.number, - torrentCountById: PropTypes.number, + torrentCountById: PropTypes.number }; diff --git a/frontend/js/components/admins/user.js b/frontend/js/components/admins/user.js index f21b142..a9508d3 100644 --- a/frontend/js/components/admins/user.js +++ b/frontend/js/components/admins/user.js @@ -1,7 +1,7 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; -import { UserEdit } from "./userEdit" +import { UserEdit } from "./userEdit"; export const User = ({ id, @@ -12,27 +12,31 @@ export const User = ({ polochonUrl, polochonName, polochonId, - token, + token }) => { return ( {id} {name} - + {polochonName !== "" ? polochonName : "-"} - {polochonUrl !== "" && - ({polochonUrl}) - } + {polochonUrl !== "" && ({polochonUrl})} {token} - + ); -} +}; User.propTypes = { id: PropTypes.string, name: PropTypes.string, @@ -57,5 +61,5 @@ User.propTypes = { token: PropTypes.string, admin: PropTypes.bool, activated: PropTypes.bool, - polochonActivated: PropTypes.bool, + polochonActivated: PropTypes.bool }; diff --git a/frontend/js/components/admins/userEdit.js b/frontend/js/components/admins/userEdit.js index 0122501..5b9788d 100644 --- a/frontend/js/components/admins/userEdit.js +++ b/frontend/js/components/admins/userEdit.js @@ -1,15 +1,15 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import { List } from "immutable" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { List } from "immutable"; -import { updateUser, deleteUser } from "../../actions/admins" +import { updateUser, deleteUser } from "../../actions/admins"; import Toggle from "react-bootstrap-toggle"; -import { PolochonSelect } from "../polochons/select" -import { FormModal } from "../forms/modal" -import { FormInput } from "../forms/input" +import { PolochonSelect } from "../polochons/select"; +import { FormModal } from "../forms/modal"; +import { FormInput } from "../forms/input"; const UserEditConnect = ({ id, @@ -21,19 +21,23 @@ const UserEditConnect = ({ polochonActivated: initPolochonActivated, updateUser, deleteUser, - publicPolochons, + publicPolochons }) => { const [modal, setModal] = useState(false); const [admin, setAdmin] = useState(initAdmin); const [activated, setActivated] = useState(initActivated); const [token, setToken] = useState(polochonToken); const [polochonId, setPolochonId] = useState(initPolochonId); - const [polochonActivated, setPolochonActivated] = useState(initPolochonActivated); + const [polochonActivated, setPolochonActivated] = useState( + initPolochonActivated + ); const [password, setPassword] = useState(""); const [confirmDelete, setConfirmDelete] = useState(false); - const handleSubmit = (e) => { - if (e) { e.preventDefault(); } + const handleSubmit = e => { + if (e) { + e.preventDefault(); + } updateUser({ userId: id, polochonToken: token, @@ -41,26 +45,26 @@ const UserEditConnect = ({ activated, polochonId, polochonActivated, - password, + password }); setModal(false); }; - const handleDeleteUser = (e) => { - if (e) { e.preventDefault(); } - if (confirmDelete) { - deleteUser(name) - setModal(false) - } else { - setConfirmDelete(true) + const handleDeleteUser = e => { + if (e) { + e.preventDefault(); } - } + if (confirmDelete) { + deleteUser(name); + setModal(false); + } else { + setConfirmDelete(true); + } + }; return ( - setModal(true)} /> + setModal(true)} /> +
+ + setActivated(!activated)} + /> +
-
- - setActivated(!activated)} +
+ + setAdmin(!admin)} + /> +
+ + -
-
- - setAdmin(!admin)} /> -
- - - - - -
- - setPolochonActivated(!polochonActivated)} + -
+ +
+ + setPolochonActivated(!polochonActivated)} + /> +
-
- -
- -
-
+
+ +
+ + ); -} +}; UserEditConnect.propTypes = { id: PropTypes.string, name: PropTypes.string, @@ -114,11 +147,13 @@ UserEditConnect.propTypes = { polochonToken: PropTypes.string, polochonId: PropTypes.string, polochonActivated: PropTypes.bool, - publicPolochons: PropTypes.instanceOf(List), + publicPolochons: PropTypes.instanceOf(List) }; -const mapStateToProps = (state) => ({ - publicPolochons: state.polochon.get("public"), +const mapStateToProps = state => ({ + publicPolochons: state.polochon.get("public") }); -export const UserEdit = connect(mapStateToProps, {updateUser, deleteUser})(UserEditConnect); +export const UserEdit = connect(mapStateToProps, { updateUser, deleteUser })( + UserEditConnect +); diff --git a/frontend/js/components/admins/userList.js b/frontend/js/components/admins/userList.js index 8e5a85f..363b0a0 100644 --- a/frontend/js/components/admins/userList.js +++ b/frontend/js/components/admins/userList.js @@ -1,15 +1,15 @@ -import React, { useEffect } from "react" -import PropTypes from "prop-types" -import { List } from "immutable" -import { connect } from "react-redux" +import React, { useEffect } from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; +import { connect } from "react-redux"; -import { User } from "./user" +import { User } from "./user"; -import { getUsers } from "../../actions/admins" -import { getPolochons } from "../../actions/polochon" +import { getUsers } from "../../actions/admins"; +import { getPolochons } from "../../actions/polochon"; const mapStateToProps = state => ({ - users: state.adminStore.get("users"), + users: state.adminStore.get("users") }); const mapDispatchToProps = { getUsers, getPolochons }; @@ -17,7 +17,7 @@ const UserListConnect = ({ users, getUsers, getPolochons }) => { useEffect(() => { getUsers(); getPolochons(); - }, [getUsers, getPolochons]) + }, [getUsers, getPolochons]); return (
@@ -35,7 +35,7 @@ const UserListConnect = ({ users, getUsers, getPolochons }) => { - {users.map((el, index) => + {users.map((el, index) => ( { polochonUrl={el.getIn(["polochon", "url"], "")} polochonName={el.getIn(["polochon", "name"], "")} /> - )} + ))}
@@ -57,7 +57,10 @@ const UserListConnect = ({ users, getUsers, getPolochons }) => { UserListConnect.propTypes = { getUsers: PropTypes.func, getPolochons: PropTypes.func, - users: PropTypes.PropTypes.instanceOf(List), + users: PropTypes.PropTypes.instanceOf(List) }; -export const UserList = connect(mapStateToProps, mapDispatchToProps)(UserListConnect); +export const UserList = connect( + mapStateToProps, + mapDispatchToProps +)(UserListConnect); diff --git a/frontend/js/components/admins/users.js b/frontend/js/components/admins/users.js index 9b79f35..2e76521 100644 --- a/frontend/js/components/admins/users.js +++ b/frontend/js/components/admins/users.js @@ -1,34 +1,35 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { List } from "immutable" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; -import { Button, Modal } from "react-bootstrap" +import { Button, Modal } from "react-bootstrap"; import Toggle from "react-bootstrap-toggle"; export const UserList = props => (
- - - - - - - - - - - - - {props.users.map((el, index) => - )} + + + + + + + + + + + + + {props.users.map((el, index) => ( + + ))}
#NameActivatedAdminPolochon URLPolochon tokenActions
#NameActivatedAdminPolochon URLPolochon tokenActions
); UserList.propTypes = { users: PropTypes.PropTypes.instanceOf(List), - updateUser: PropTypes.func, + updateUser: PropTypes.func }; const User = function(props) { @@ -39,8 +40,12 @@ const User = function(props) { {props.data.get("id")} {props.data.get("Name")} - - + + + + + + {polochonUrl} {polochonToken} @@ -53,10 +58,10 @@ const User = function(props) { ); -} +}; User.propTypes = { data: PropTypes.object, - updateUser: PropTypes.func, + updateUser: PropTypes.func }; const UserAdminStatus = props => ( @@ -65,7 +70,9 @@ const UserAdminStatus = props => ( UserAdminStatus.propTypes = { admin: PropTypes.bool.isRequired }; const UserActivationStatus = props => ( - + ); UserActivationStatus.propTypes = { activated: PropTypes.bool.isRequired }; @@ -77,20 +84,25 @@ function UserEdit(props) { const [token, setToken] = useState(props.polochonToken); const handleSubmit = function(e) { - if (e) { e.preventDefault(); } + if (e) { + e.preventDefault(); + } props.updateUser({ userId: props.data.get("id"), admin: admin, activated: activated, polochonUrl: url, - polochonToken: token, + polochonToken: token }); setModal(false); }; return ( - setModal(true)}> + setModal(true)} + > setModal(false)}> @@ -99,30 +111,53 @@ function UserEdit(props) { -
handleSubmit(ev)}> + handleSubmit(ev)}>
- setActivated(!activated)} + setActivated(!activated)} />
- setAdmin(!admin)} /> + setAdmin(!admin)} + />
- setUrl(e.target.value)}/> + setUrl(e.target.value)} + />
- setToken(e.target.value)} /> + setToken(e.target.value)} + />
- +
@@ -133,5 +168,5 @@ UserEdit.propTypes = { data: PropTypes.object, updateUser: PropTypes.func, polochonUrl: PropTypes.string, - polochonToken: PropTypes.string, + polochonToken: PropTypes.string }; diff --git a/frontend/js/components/alerts/alert.js b/frontend/js/components/alerts/alert.js index d006d1e..a9b5674 100644 --- a/frontend/js/components/alerts/alert.js +++ b/frontend/js/components/alerts/alert.js @@ -1,20 +1,20 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; import SweetAlert from "react-bootstrap-sweetalert"; -import { connect } from "react-redux" +import { connect } from "react-redux"; -import { dismissAlert } from "../../actions/alerts" +import { dismissAlert } from "../../actions/alerts"; -const mapStateToProps = (state) => ({ +const mapStateToProps = state => ({ show: state.alerts.get("show"), title: state.alerts.get("message"), - type: state.alerts.get("type"), + type: state.alerts.get("type") }); const mapDispatchToProps = { dismissAlert }; -const Alert = (props) => { +const Alert = props => { if (!props.show) { - return null + return null; } return ( @@ -23,13 +23,13 @@ const Alert = (props) => { title={props.title} onConfirm={props.dismissAlert} /> - ) -} + ); +}; Alert.propTypes = { show: PropTypes.bool.isRequired, title: PropTypes.string.isRequired, dismissAlert: PropTypes.func.isRequired, - type: PropTypes.string, + type: PropTypes.string }; export default connect(mapStateToProps, mapDispatchToProps)(Alert); diff --git a/frontend/js/components/buttons/download.js b/frontend/js/components/buttons/download.js index 8e9a3ed..1403e2c 100644 --- a/frontend/js/components/buttons/download.js +++ b/frontend/js/components/buttons/download.js @@ -1,11 +1,13 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { List } from "immutable" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; -import Modal from "react-bootstrap/Modal" +import Modal from "react-bootstrap/Modal"; export const DownloadAndStream = ({ url, name, subtitles }) => { - if (!url || url === "") { return null; } + if (!url || url === "") { + return null; + } return ( @@ -13,11 +15,11 @@ export const DownloadAndStream = ({ url, name, subtitles }) => { ); -} +}; DownloadAndStream.propTypes = { url: PropTypes.string, name: PropTypes.string, - subtitles: PropTypes.instanceOf(List), + subtitles: PropTypes.instanceOf(List) }; const DownloadButton = ({ url }) => ( @@ -39,13 +41,22 @@ const StreamButton = ({ name, url, subtitles }) => { { e.preventDefault(); setShowModal(true) }}> + onClick={e => { + e.preventDefault(); + setShowModal(true); + }} + > Play - setShowModal(false)} size="lg" centered> + setShowModal(false)} + size="lg" + centered + > {name} @@ -53,11 +64,11 @@ const StreamButton = ({ name, url, subtitles }) => { ); -} +}; StreamButton.propTypes = { name: PropTypes.string.isRequired, url: PropTypes.string.isRequired, - subtitles: PropTypes.instanceOf(List), + subtitles: PropTypes.instanceOf(List) }; const Player = ({ url, subtitles }) => { @@ -65,24 +76,27 @@ const Player = ({ url, subtitles }) => { return (
); -} +}; Player.propTypes = { subtitles: PropTypes.instanceOf(List), - url: PropTypes.string.isRequired, + url: PropTypes.string.isRequired }; Player.defaultProps = { - subtitles: List(), + subtitles: List() }; diff --git a/frontend/js/components/buttons/imdb.js b/frontend/js/components/buttons/imdb.js index 46bd445..42e0d2d 100644 --- a/frontend/js/components/buttons/imdb.js +++ b/frontend/js/components/buttons/imdb.js @@ -1,19 +1,22 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; export const ImdbBadge = ({ imdbId }) => { - if (imdbId === undefined) { return null } + if (imdbId === undefined) { + return null; + } return (
+ href={`https://www.imdb.com/title/${imdbId}`} + > IMDb
); -} +}; ImdbBadge.propTypes = { imdbId: PropTypes.string }; ImdbBadge.defaultProps = { imdbId: undefined }; diff --git a/frontend/js/components/buttons/showMore.js b/frontend/js/components/buttons/showMore.js index d2a3964..333dce6 100644 --- a/frontend/js/components/buttons/showMore.js +++ b/frontend/js/components/buttons/showMore.js @@ -1,11 +1,11 @@ -import React, { useState, useEffect } from "react" -import PropTypes from "prop-types" +import React, { useState, useEffect } from "react"; +import PropTypes from "prop-types"; -export const ShowMore = ({ children, id, inLibrary }) => { - const [ display, setDisplay ] = useState(!inLibrary) +export const ShowMore = ({ children, id, inLibrary }) => { + const [display, setDisplay] = useState(!inLibrary); useEffect(() => { - setDisplay(!inLibrary); + setDisplay(!inLibrary); }, [id, inLibrary]); if (!display) { @@ -18,21 +18,18 @@ export const ShowMore = ({ children, id, inLibrary }) => { More options ...
- ) + ); } - return ({children}) -} + return {children}; +}; ShowMore.propTypes = { id: PropTypes.string, inLibrary: PropTypes.bool.isRequired, - children: PropTypes.oneOf( - PropTypes.object, - PropTypes.array, - ), -} + children: PropTypes.oneOf(PropTypes.object, PropTypes.array) +}; ShowMore.defaultProps = { id: "", - inLibrary: false, -} + inLibrary: false +}; diff --git a/frontend/js/components/buttons/subtitles.js b/frontend/js/components/buttons/subtitles.js index bcf8510..add3937 100644 --- a/frontend/js/components/buttons/subtitles.js +++ b/frontend/js/components/buttons/subtitles.js @@ -1,73 +1,72 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { List } from "immutable" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; -import Dropdown from "react-bootstrap/Dropdown" +import Dropdown from "react-bootstrap/Dropdown"; export const SubtitlesButton = ({ subtitles, inLibrary, searching, - search, + search }) => { - if (inLibrary === false) { return null } + if (inLibrary === false) { + return null; + } /* eslint-disable */ const [show, setShow] = useState(false); /* eslint-enable */ - const onSelect = (eventKey) => { + const onSelect = eventKey => { if (eventKey === null || eventKey != 1) { setShow(false); } - } + }; const onToggle = (isOpen, event, metadata) => { // Don't close on select if (metadata && metadata.source !== "select") { setShow(isOpen); } - } + }; - const count = (subtitles && subtitles.size !== 0) ? subtitles.size : 0; + const count = subtitles && subtitles.size !== 0 ? subtitles.size : 0; return ( Subtitles - - {count} - + {count} - - + + Automatic search + {count > 0 && ( + + + + Available subtitles + + + )} {count > 0 && - - - - - Available subtitles - - - - } - {count > 0 && subtitles.toIndexedSeq().map((subtitle, index) => ( - - {subtitle.get("language").split("_")[1]} - - ))} + subtitles.toIndexedSeq().map((subtitle, index) => ( + + {subtitle.get("language").split("_")[1]} + + ))} ); -} +}; SubtitlesButton.propTypes = { subtitles: PropTypes.instanceOf(List), inLibrary: PropTypes.bool.isRequired, searching: PropTypes.bool.isRequired, - search: PropTypes.func.isRequired, -} + search: PropTypes.func.isRequired +}; diff --git a/frontend/js/components/buttons/torrents.js b/frontend/js/components/buttons/torrents.js index 6ce5716..7f061cf 100644 --- a/frontend/js/components/buttons/torrents.js +++ b/frontend/js/components/buttons/torrents.js @@ -1,19 +1,19 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { List } from "immutable" -import { connect } from "react-redux" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; +import { connect } from "react-redux"; -import { prettySize } from "../../utils" -import { addTorrent } from "../../actions/torrents" +import { prettySize } from "../../utils"; +import { addTorrent } from "../../actions/torrents"; -import Dropdown from "react-bootstrap/Dropdown" +import Dropdown from "react-bootstrap/Dropdown"; function buildMenuItems(torrents) { if (!torrents || torrents.size === 0) { return []; } - const t = torrents.groupBy((el) => el.get("source")); + const t = torrents.groupBy(el => el.get("source")); // Build the array of entries let entries = []; @@ -22,7 +22,7 @@ function buildMenuItems(torrents) { // Push the title entries.push({ type: "header", - value: source, + value: source }); // Push the torrents @@ -31,7 +31,7 @@ function buildMenuItems(torrents) { type: "entry", quality: torrent.get("quality"), url: torrent.get("url"), - size: torrent.get("size"), + size: torrent.get("size") }); } @@ -45,32 +45,26 @@ function buildMenuItems(torrents) { return entries; } -const torrentsButton = ({ - torrents, - search, - searching, - addTorrent, - url, -}) => { +const torrentsButton = ({ torrents, search, searching, addTorrent, url }) => { /* eslint-disable */ const [show, setShow] = useState(false); /* eslint-enable */ const entries = buildMenuItems(torrents); - const count = (torrents && torrents.size !== 0) ? torrents.size : 0; + const count = torrents && torrents.size !== 0 ? torrents.size : 0; - const onSelect = (eventKey) => { + const onSelect = eventKey => { // Close the dropdown if the eventkey is not specified if (eventKey === null) { setShow(false); } - } + }; const onToggle = (isOpen, event, metadata) => { // Don't close on select if (metadata && metadata.source !== "select") { setShow(isOpen); } - } + }; return ( @@ -78,23 +72,19 @@ const torrentsButton = ({ Torrents - - {count} - + {count} - - + + Automatic search - + Manual search - {entries.length > 0 && - - } + {entries.length > 0 && } {entries.map((e, index) => { switch (e.type) { case "header": @@ -104,16 +94,14 @@ const torrentsButton = ({ ); case "divider": - return ( - - ); + return ; case "entry": return ( addTorrent(e.url)}> {e.quality} - {e.size !== 0 && - ({prettySize(e.size)}) - } + {e.size !== 0 && ( + ({prettySize(e.size)}) + )} ); } @@ -122,16 +110,16 @@ const torrentsButton = ({ ); -} +}; torrentsButton.propTypes = { torrents: PropTypes.instanceOf(List), searching: PropTypes.bool, search: PropTypes.func.isRequired, addTorrent: PropTypes.func.isRequired, - url: PropTypes.string, -} + url: PropTypes.string +}; torrentsButton.defaultProps = { - torrents: List(), -} + torrents: List() +}; -export const TorrentsButton = connect(null, {addTorrent})(torrentsButton); +export const TorrentsButton = connect(null, { addTorrent })(torrentsButton); diff --git a/frontend/js/components/buttons/wishlist.js b/frontend/js/components/buttons/wishlist.js index 7bba31a..3e3f51e 100644 --- a/frontend/js/components/buttons/wishlist.js +++ b/frontend/js/components/buttons/wishlist.js @@ -1,5 +1,5 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; export const WishlistButton = ({ wishlisted, wishlist }) => { return ( @@ -10,8 +10,8 @@ export const WishlistButton = ({ wishlisted, wishlist }) => { /> ); -} +}; WishlistButton.propTypes = { wishlisted: PropTypes.bool.isRequired, - wishlist: PropTypes.func.isRequired, -} + wishlist: PropTypes.func.isRequired +}; diff --git a/frontend/js/components/details/genres.js b/frontend/js/components/details/genres.js index 4092389..d739ed2 100644 --- a/frontend/js/components/details/genres.js +++ b/frontend/js/components/details/genres.js @@ -1,14 +1,17 @@ -import React from "react" -import PropTypes from "prop-types" -import { List } from "immutable" +import React from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; export const Genres = ({ genres }) => { - if (genres.size === 0) { return null } + if (genres.size === 0) { + return null; + } // Uppercase first genres - const prettyGenres = genres.toJS().map( - (word) => word[0].toUpperCase() + word.substr(1) - ).join(", "); + const prettyGenres = genres + .toJS() + .map(word => word[0].toUpperCase() + word.substr(1)) + .join(", "); return ( @@ -16,6 +19,6 @@ export const Genres = ({ genres }) => { {prettyGenres} ); -} +}; Genres.propTypes = { genres: PropTypes.instanceOf(List) }; Genres.defaultProps = { genres: List() }; diff --git a/frontend/js/components/details/plot.js b/frontend/js/components/details/plot.js index 2bbe10d..4bd4cc8 100644 --- a/frontend/js/components/details/plot.js +++ b/frontend/js/components/details/plot.js @@ -1,12 +1,12 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; export const Plot = ({ plot }) => { - if (plot === "") { return null } + if (plot === "") { + return null; + } - return ( - {plot} - ); -} + return {plot}; +}; Plot.propTypes = { plot: PropTypes.string }; Plot.defaultProps = { plot: "" }; diff --git a/frontend/js/components/details/polochon.js b/frontend/js/components/details/polochon.js index f3e8713..75a038b 100644 --- a/frontend/js/components/details/polochon.js +++ b/frontend/js/components/details/polochon.js @@ -1,26 +1,20 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; export const PolochonMetadata = ({ quality, container, videoCodec, audioCodec, - releaseGroup, + releaseGroup }) => { if (!quality || quality === "") { return null; } - const metadata = [ - quality, - container, - videoCodec, - audioCodec, - releaseGroup, - ]. - filter(m => (m && m !== "")). - join(", ") + const metadata = [quality, container, videoCodec, audioCodec, releaseGroup] + .filter(m => m && m !== "") + .join(", "); return ( @@ -28,11 +22,11 @@ export const PolochonMetadata = ({ {metadata} ); -} +}; PolochonMetadata.propTypes = { quality: PropTypes.string, container: PropTypes.string, videoCodec: PropTypes.string, audioCodec: PropTypes.string, - releaseGroup: PropTypes.string, + releaseGroup: PropTypes.string }; diff --git a/frontend/js/components/details/rating.js b/frontend/js/components/details/rating.js index b1e4f5a..6736eb9 100644 --- a/frontend/js/components/details/rating.js +++ b/frontend/js/components/details/rating.js @@ -1,24 +1,24 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; export const Rating = ({ rating, votes }) => { - if (rating === 0) { return null; } + if (rating === 0) { + return null; + } return ( {Number(rating).toFixed(1)} - {votes !== 0 && - ({votes} votes) - } + {votes !== 0 && ({votes} votes)} ); -} +}; Rating.propTypes = { rating: PropTypes.number, - votes: PropTypes.number, + votes: PropTypes.number }; Rating.defaultProps = { rating: 0, - votes: 0, + votes: 0 }; diff --git a/frontend/js/components/details/releaseDate.js b/frontend/js/components/details/releaseDate.js index 1470a61..14a831e 100644 --- a/frontend/js/components/details/releaseDate.js +++ b/frontend/js/components/details/releaseDate.js @@ -1,35 +1,42 @@ -import React from "react" -import PropTypes from "prop-types" -import moment from "moment" +import React from "react"; +import PropTypes from "prop-types"; +import moment from "moment"; -const prettyDate = (input) => { +const prettyDate = input => { switch (typeof input) { case "string": - if (input === "") { return "" } + if (input === "") { + return ""; + } break; case "number": - if (input === 0) { return "" } - return input + if (input === 0) { + return ""; + } + return input; default: return input; } const date = moment(input); - if (!date.isValid()) { return "" } + if (!date.isValid()) { + return ""; + } let output = date.format("DD/MM/YYYY"); - if ((date > moment().subtract(1, "month")) - && (date < moment().add(1, "month"))) { - output += " (" + date.fromNow() + ")" + if (date > moment().subtract(1, "month") && date < moment().add(1, "month")) { + output += " (" + date.fromNow() + ")"; } - return output -} + return output; +}; export const ReleaseDate = ({ date }) => { const formattedDate = prettyDate(date); - if (formattedDate === "") { return null } + if (formattedDate === "") { + return null; + } return ( @@ -37,11 +44,8 @@ export const ReleaseDate = ({ date }) => { {formattedDate} ); -} +}; ReleaseDate.propTypes = { - date: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.number, - ]), + date: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) }; ReleaseDate.defaultProps = { date: "" }; diff --git a/frontend/js/components/details/runtime.js b/frontend/js/components/details/runtime.js index 1d5f2a5..c801788 100644 --- a/frontend/js/components/details/runtime.js +++ b/frontend/js/components/details/runtime.js @@ -1,10 +1,12 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; -import { prettyDurationFromMinutes } from "../../utils" +import { prettyDurationFromMinutes } from "../../utils"; export const Runtime = ({ runtime }) => { - if (runtime === 0) { return null; } + if (runtime === 0) { + return null; + } return ( @@ -12,6 +14,6 @@ export const Runtime = ({ runtime }) => {  {prettyDurationFromMinutes(runtime)} ); -} +}; Runtime.propTypes = { runtime: PropTypes.number }; Runtime.defaultProps = { runtime: 0 }; diff --git a/frontend/js/components/details/title.js b/frontend/js/components/details/title.js index 3c29fde..f8839a0 100644 --- a/frontend/js/components/details/title.js +++ b/frontend/js/components/details/title.js @@ -1,10 +1,12 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; -import { WishlistButton } from "../buttons/wishlist" +import { WishlistButton } from "../buttons/wishlist"; export const Title = ({ title, wishlist, wishlisted }) => { - if (title === "") { return null; } + if (title === "") { + return null; + } return ( @@ -12,12 +14,12 @@ export const Title = ({ title, wishlist, wishlisted }) => { {title} ); -} +}; Title.propTypes = { title: PropTypes.string, wishlist: PropTypes.func, - wishlisted: PropTypes.bool, + wishlisted: PropTypes.bool }; Title.defaultProps = { - title: "", + title: "" }; diff --git a/frontend/js/components/details/tracking.js b/frontend/js/components/details/tracking.js index 935213f..1b1335f 100644 --- a/frontend/js/components/details/tracking.js +++ b/frontend/js/components/details/tracking.js @@ -1,7 +1,12 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; -export const TrackingLabel = ({ wishlisted, inLibrary, trackedSeason, trackedEpisode }) => { +export const TrackingLabel = ({ + wishlisted, + inLibrary, + trackedSeason, + trackedEpisode +}) => { if (wishlisted === false) { return null; } @@ -14,14 +19,14 @@ export const TrackingLabel = ({ wishlisted, inLibrary, trackedSeason, trackedEpi return null; } - let str = "" + let str = ""; if (trackedSeason === 0 && trackedEpisode === 0) { str = "All the episodes will be downloaded automatically"; } else if (trackedSeason > 0 && trackedEpisode > 0) { str = `All the episodes will be downloaded automatically starting from season ${trackedSeason} episode ${trackedEpisode}`; } else { - str = "This movie will be downloaded automatically" + str = "This movie will be downloaded automatically"; } return ( @@ -31,11 +36,11 @@ export const TrackingLabel = ({ wishlisted, inLibrary, trackedSeason, trackedEpi {str} - ) -} + ); +}; TrackingLabel.propTypes = { wishlisted: PropTypes.bool, inLibrary: PropTypes.bool, trackedSeason: PropTypes.number, - trackedEpisode: PropTypes.number, + trackedEpisode: PropTypes.number }; diff --git a/frontend/js/components/forms/input.js b/frontend/js/components/forms/input.js index 8da4c85..4fd6d8f 100644 --- a/frontend/js/components/forms/input.js +++ b/frontend/js/components/forms/input.js @@ -1,22 +1,20 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; export const FormInput = ({ label, value, updateValue }) => { return (
- + updateValue(e.target.value)} + onChange={e => updateValue(e.target.value)} />
- ) -} + ); +}; FormInput.propTypes = { label: PropTypes.string, value: PropTypes.string, - updateValue: PropTypes.func, + updateValue: PropTypes.func }; diff --git a/frontend/js/components/forms/modal.js b/frontend/js/components/forms/modal.js index 5baef5f..4ee6cc4 100644 --- a/frontend/js/components/forms/modal.js +++ b/frontend/js/components/forms/modal.js @@ -1,7 +1,7 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; -import { Modal } from "react-bootstrap" +import { Modal } from "react-bootstrap"; export const FormModal = ({ show, @@ -9,41 +9,44 @@ export const FormModal = ({ title, icon, handleSubmit, - children, + children }) => { const submit = function(e) { - if (e) { e.preventDefault(); } + if (e) { + e.preventDefault(); + } handleSubmit(); }; return ( - setShow(false)}> - - - - {title} - - - -
submit(ev)}> - {children} -
-
- -
Apply
-
setShow(false)}>Close
-
-
- ) -} + setShow(false)}> + + + + {title} + + + +
submit(ev)}> + {children} +
+
+ +
+ Apply +
+
setShow(false)}> + Close +
+
+
+ ); +}; FormModal.propTypes = { show: PropTypes.bool, setShow: PropTypes.func, icon: PropTypes.string, title: PropTypes.string, handleSubmit: PropTypes.func, - children: PropTypes.oneOf( - PropTypes.object, - PropTypes.array, - ), + children: PropTypes.oneOf(PropTypes.object, PropTypes.array) }; diff --git a/frontend/js/components/list/details.js b/frontend/js/components/list/details.js index f996447..717da0a 100644 --- a/frontend/js/components/list/details.js +++ b/frontend/js/components/list/details.js @@ -1,24 +1,28 @@ -import React from "react" -import PropTypes from "prop-types" -import { Map } from "immutable" +import React from "react"; +import PropTypes from "prop-types"; +import { Map } from "immutable"; -import { inLibrary, isWishlisted } from "../../utils" +import { inLibrary, isWishlisted } from "../../utils"; -import { DownloadAndStream } from "../buttons/download" -import { ImdbBadge } from "../buttons/imdb" +import { DownloadAndStream } from "../buttons/download"; +import { ImdbBadge } from "../buttons/imdb"; -import { TrackingLabel } from "../details/tracking" -import { Genres } from "../details/genres" -import { Plot } from "../details/plot" -import { PolochonMetadata } from "../details/polochon" -import { Rating } from "../details/rating" -import { ReleaseDate } from "../details/releaseDate" -import { Runtime } from "../details/runtime" -import { Title } from "../details/title" +import { TrackingLabel } from "../details/tracking"; +import { Genres } from "../details/genres"; +import { Plot } from "../details/plot"; +import { PolochonMetadata } from "../details/polochon"; +import { Rating } from "../details/rating"; +import { ReleaseDate } from "../details/releaseDate"; +import { Runtime } from "../details/runtime"; +import { Title } from "../details/title"; -const ListDetails = (props) => { - if (props.data === undefined) { return null } - if (props.loading) { return null } +const ListDetails = props => { + if (props.data === undefined) { + return null; + } + if (props.loading) { + return null; + } return (
@@ -61,11 +65,11 @@ const ListDetails = (props) => {
); -} +}; ListDetails.propTypes = { data: PropTypes.instanceOf(Map), wishlist: PropTypes.func, loading: PropTypes.bool, - children: PropTypes.object, + children: PropTypes.object }; export default ListDetails; diff --git a/frontend/js/components/list/explorerOptions.js b/frontend/js/components/list/explorerOptions.js index 7405d21..83193c1 100644 --- a/frontend/js/components/list/explorerOptions.js +++ b/frontend/js/components/list/explorerOptions.js @@ -1,6 +1,6 @@ -import React from "react" -import { withRouter } from "react-router-dom" -import { Form, FormGroup, FormControl, FormLabel } from "react-bootstrap" +import React from "react"; +import { withRouter } from "react-router-dom"; +import { Form, FormGroup, FormControl, FormLabel } from "react-bootstrap"; class ExplorerOptions extends React.PureComponent { constructor(props) { @@ -11,27 +11,34 @@ class ExplorerOptions extends React.PureComponent { handleSourceChange(event) { let source = event.target.value; let category = this.props.options.get(event.target.value).first(); - this.props.history.push(`/${this.props.type}/explore/${source}/${category}`); + this.props.history.push( + `/${this.props.type}/explore/${source}/${category}` + ); } handleCategoryChange(event) { let source = this.props.params.source; let category = event.target.value; - this.props.history.push(`/${this.props.type}/explore/${source}/${category}`); + this.props.history.push( + `/${this.props.type}/explore/${source}/${category}` + ); } propsValid(props) { - if (!props.params - || !props.params.source - || !props.params.category - || (props.params.source === "") - || (props.params.category === "")) { - return false + if ( + !props.params || + !props.params.source || + !props.params.category || + props.params.source === "" || + props.params.category === "" + ) { + return false; } return true; } prettyName(name) { - return name.replace("_", " ") + return name + .replace("_", " ") .split(" ") - .map((w) => w[0].toUpperCase() + w.substr(1)) + .map(w => w[0].toUpperCase() + w.substr(1)) .join(" "); } render() { @@ -47,7 +54,7 @@ class ExplorerOptions extends React.PureComponent { // Invalid props if (!this.propsValid(this.props)) { - return + return; } let source = this.props.params.source; @@ -70,7 +77,10 @@ class ExplorerOptions extends React.PureComponent { > {this.props.options.keySeq().map(function(source) { return ( - ) + + ); }, this)} @@ -85,7 +95,11 @@ class ExplorerOptions extends React.PureComponent { value={category} > {categories.map(function(category) { - return () + return ( + + ); }, this)} diff --git a/frontend/js/components/list/filter.js b/frontend/js/components/list/filter.js index 0299a5f..221d133 100644 --- a/frontend/js/components/list/filter.js +++ b/frontend/js/components/list/filter.js @@ -1,5 +1,5 @@ -import React, { useState, useEffect } from "react" -import PropTypes from "prop-types" +import React, { useState, useEffect } from "react"; +import PropTypes from "prop-types"; const ListFilter = ({ placeHolder, updateFilter }) => { const [filter, setFilter] = useState(""); @@ -13,18 +13,21 @@ const ListFilter = ({ placeHolder, updateFilter }) => { return (
- setFilter(e.target.value)} - value={filter} /> + onChange={e => setFilter(e.target.value)} + value={filter} + />
Filter
); -} +}; ListFilter.propTypes = { updateFilter: PropTypes.func.isRequired, - placeHolder: PropTypes.string.isRequired, + placeHolder: PropTypes.string.isRequired }; export default ListFilter; diff --git a/frontend/js/components/list/poster.js b/frontend/js/components/list/poster.js index 4b6e3b6..96a8e68 100644 --- a/frontend/js/components/list/poster.js +++ b/frontend/js/components/list/poster.js @@ -1,11 +1,13 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; -import EmptyImg from "../../../img/noimage.png" +import EmptyImg from "../../../img/noimage.png"; const Poster = ({ url, selected, onClick, onDoubleClick }) => { - const className = selected ? "border-primary thumbnail-selected" : "border-secondary"; - const src = (url === "") ? EmptyImg : url; + const className = selected + ? "border-primary thumbnail-selected" + : "border-secondary"; + const src = url === "" ? EmptyImg : url; return ( { className={`my-1 m-md-2 img-thumbnail object-fit-cover ${className}`} /> ); -} +}; Poster.propTypes = { url: PropTypes.string, selected: PropTypes.bool.isRequired, onClick: PropTypes.func, - onDoubleClick: PropTypes.func, + onDoubleClick: PropTypes.func }; export default Poster; diff --git a/frontend/js/components/list/posters.js b/frontend/js/components/list/posters.js index daa40dd..2e78a06 100644 --- a/frontend/js/components/list/posters.js +++ b/frontend/js/components/list/posters.js @@ -1,18 +1,18 @@ -import React, { useState, useEffect, useCallback } from "react" -import PropTypes from "prop-types" -import { OrderedMap, Map } from "immutable" +import React, { useState, useEffect, useCallback } from "react"; +import PropTypes from "prop-types"; +import { OrderedMap, Map } from "immutable"; import fuzzy from "fuzzy"; import InfiniteScroll from "react-infinite-scroll-component"; -import ListFilter from "./filter" -import ExplorerOptions from "./explorerOptions" -import Poster from "./poster" +import ListFilter from "./filter"; +import ExplorerOptions from "./explorerOptions"; +import Poster from "./poster"; -import Loader from "../loader/loader" +import Loader from "../loader/loader"; -const ListPosters = (props) => { +const ListPosters = props => { if (props.loading) { - return (); + return ; } let elmts = props.data; @@ -20,23 +20,24 @@ const ListPosters = (props) => { // Filter the list of elements if (props.filter !== "") { - elmts = elmts.filter((v) => fuzzy.test(props.filter, v.get("title"))); + elmts = elmts.filter(v => fuzzy.test(props.filter, v.get("title"))); } else { elmts = elmts.slice(0, listSize.items); } // Chose when to display filter / explore options let displayFilter = true; - if ((props.params - && props.params.category - && props.params.category !== "" - && props.params.source - && props.params.source !== "") - || (listSize === 0)) { + if ( + (props.params && + props.params.category && + props.params.category !== "" && + props.params.source && + props.params.source !== "") || + listSize === 0 + ) { displayFilter = false; } - let displayExplorerOptions = false; if (listSize !== 0) { displayExplorerOptions = !displayFilter; @@ -44,12 +45,12 @@ const ListPosters = (props) => { return (
- {displayFilter && + {displayFilter && ( - } + )} { />
); -} +}; ListPosters.propTypes = { data: PropTypes.instanceOf(OrderedMap), onClick: PropTypes.func, @@ -79,34 +80,39 @@ ListPosters.propTypes = { type: PropTypes.string.isRequired, placeHolder: PropTypes.string.isRequired, updateFilter: PropTypes.func.isRequired, - filter: PropTypes.string, + filter: PropTypes.string }; export default ListPosters; -const Posters = (props) => { +const Posters = props => { const addMoreCount = 20; const [size, setSize] = useState(0); const [postersPerRow, setPostersPerRow] = useState(0); const [posterHeight, setPosterHeight] = useState(0); const loadMore = () => { - if ((size === props.elmts.size)) { return } + if (size === props.elmts.size) { + return; + } - const newSize = (((size + addMoreCount) >= props.elmts.size) - ? props.elmts.size - : size + addMoreCount); + const newSize = + size + addMoreCount >= props.elmts.size + ? props.elmts.size + : size + addMoreCount; setSize(newSize); - } + }; useEffect(() => { - loadMore() + loadMore(); }, [props.elmts.size]); - const move = (event) => { + const move = event => { // Only run the function if nothing else if actively focused - if (document.activeElement.tagName.toLowerCase() !== "body") { return } + if (document.activeElement.tagName.toLowerCase() !== "body") { + return; + } let diff = 0; let moveFocus = 0; @@ -121,11 +127,11 @@ const Posters = (props) => { diff = -1; break; case "k": - diff = -1*postersPerRow; - moveFocus = -1*posterHeight; + diff = -1 * postersPerRow; + moveFocus = -1 * posterHeight; break; case "j": - diff = postersPerRow; + diff = postersPerRow; moveFocus = posterHeight; break; default: @@ -138,8 +144,8 @@ const Posters = (props) => { var newIdx = idx + diff; // Handle edge cases - if (newIdx > props.elmts.size -1) { - newIdx = props.elmts.size -1; + if (newIdx > props.elmts.size - 1) { + newIdx = props.elmts.size - 1; } else if (newIdx < 0) { newIdx = 0; } @@ -152,33 +158,38 @@ const Posters = (props) => { if (moveFocus !== 0) { window.scrollBy(0, moveFocus); } - } + }; const posterCount = useCallback(node => { - if (node === null) { return } + if (node === null) { + return; + } const parentWidth = node.getBoundingClientRect().width; const childContainer = node.getElementsByClassName("img-thumbnail"); let childWidth = 0; let posterHeight = 0; - if ((childContainer !== null) && (childContainer.item(0) !== null)) { + if (childContainer !== null && childContainer.item(0) !== null) { const child = childContainer.item(0); - childWidth = child.getBoundingClientRect().width + child.getBoundingClientRect().left; + childWidth = + child.getBoundingClientRect().width + + child.getBoundingClientRect().left; posterHeight = child.getBoundingClientRect().height; } - let numberPerRow = (childWidth >= parentWidth) ? 1 : Math.floor(parentWidth/childWidth); + let numberPerRow = + childWidth >= parentWidth ? 1 : Math.floor(parentWidth / childWidth); setPostersPerRow(numberPerRow); setPosterHeight(posterHeight); - }) + }); useEffect(() => { document.onkeypress = move; return () => { document.onkeypress = null; - } - }, [move]) + }; + }, [move]); - if (props.elmts.size === 0) { + if (props.elmts.size === 0) { return (

No result

@@ -192,32 +203,35 @@ const Posters = (props) => { className="poster-list d-flex flex-column flex-sm-row flex-sm-wrap justify-content-around" dataLength={size} next={loadMore} - hasMore={(size !== props.elmts.size)} + hasMore={size !== props.elmts.size} loader={} > - {props.elmts.slice(0, size).toIndexedSeq().map(function(el, index) { - const imdbId = el.get("imdb_id"); - const selected = (imdbId === props.selectedImdbId) ? true : false; + {props.elmts + .slice(0, size) + .toIndexedSeq() + .map(function(el, index) { + const imdbId = el.get("imdb_id"); + const selected = imdbId === props.selectedImdbId ? true : false; - return ( - props.selectPoster(imdbId)} - onDoubleClick={() => props.onDoubleClick(imdbId)} - /> - ) - } ,this)} + return ( + props.selectPoster(imdbId)} + onDoubleClick={() => props.onDoubleClick(imdbId)} + /> + ); + }, this)}
); -} +}; Posters.propTypes = { elmts: PropTypes.instanceOf(OrderedMap), selectedImdbId: PropTypes.string, loading: PropTypes.bool.isRequired, onDoubleClick: PropTypes.func, onKeyEnter: PropTypes.func, - selectPoster: PropTypes.func, + selectPoster: PropTypes.func }; diff --git a/frontend/js/components/loader/loader.js b/frontend/js/components/loader/loader.js index e90d004..63e5170 100644 --- a/frontend/js/components/loader/loader.js +++ b/frontend/js/components/loader/loader.js @@ -1,14 +1,9 @@ -import React from "react" -import Loading from "react-loading" +import React from "react"; +import Loading from "react-loading"; const Loader = () => (
- +
); export default Loader; diff --git a/frontend/js/components/modules/modules.js b/frontend/js/components/modules/modules.js index 2fd00ff..02da6f3 100644 --- a/frontend/js/components/modules/modules.js +++ b/frontend/js/components/modules/modules.js @@ -1,38 +1,40 @@ -import React from "react" -import Loader from "../loader/loader" -import PropTypes from "prop-types" -import { Map, List } from "immutable" +import React from "react"; +import Loader from "../loader/loader"; +import PropTypes from "prop-types"; +import { Map, List } from "immutable"; // TODO: udpate this -import { OverlayTrigger, Tooltip } from "react-bootstrap" +import { OverlayTrigger, Tooltip } from "react-bootstrap"; -const Modules = (props) => { +const Modules = props => { if (props.isLoading) { - return + return ; } return (
- {props.modules && props.modules.keySeq().map((value, key) => ( - - ))} + {props.modules && + props.modules + .keySeq() + .map((value, key) => ( + + ))}
); -} +}; Modules.propTypes = { isLoading: PropTypes.bool.isRequired, - modules: PropTypes.instanceOf(Map), + modules: PropTypes.instanceOf(Map) }; export default Modules; -const capitalize = (string) => - string.charAt(0).toUpperCase() + string.slice(1); +const capitalize = string => string.charAt(0).toUpperCase() + string.slice(1); -const ModulesByVideoType = (props) => ( +const ModulesByVideoType = props => (
@@ -40,11 +42,7 @@ const ModulesByVideoType = (props) => (
{props.data.keySeq().map((value, key) => ( - + ))}
@@ -52,22 +50,16 @@ const ModulesByVideoType = (props) => ( ); ModulesByVideoType.propTypes = { videoType: PropTypes.string.isRequired, - data: PropTypes.instanceOf(Map), + data: PropTypes.instanceOf(Map) }; -const ModuleByType = (props) => ( +const ModuleByType = props => (

{capitalize(props.type)}

{props.data.map(function(value, key) { - return ( - - ); + return ; })}
@@ -75,41 +67,43 @@ const ModuleByType = (props) => ( ); ModuleByType.propTypes = { type: PropTypes.string.isRequired, - data: PropTypes.instanceOf(List), + data: PropTypes.instanceOf(List) }; -const Module = (props) => { +const Module = props => { let iconClass, prettyStatus, badgeClass; const name = props.data.get("name"); - switch(props.data.get("status")) { + switch (props.data.get("status")) { case "ok": - iconClass = "fa fa-check-circle" - badgeClass = "badge badge-pill badge-success" - prettyStatus = "OK" + iconClass = "fa fa-check-circle"; + badgeClass = "badge badge-pill badge-success"; + prettyStatus = "OK"; break; case "fail": - iconClass = "fa fa-times-circle" - badgeClass = "badge badge-pill badge-danger" - prettyStatus = "Fail" + iconClass = "fa fa-times-circle"; + badgeClass = "badge badge-pill badge-danger"; + prettyStatus = "Fail"; break; case "not_implemented": - iconClass = "fa fa-question-circle" - badgeClass = "badge badge-pill badge-default" - prettyStatus = "Not implemented" + iconClass = "fa fa-question-circle"; + badgeClass = "badge badge-pill badge-default"; + prettyStatus = "Not implemented"; break; default: - iconClass = "fa fa-question-circle" - badgeClass = "badge badge-pill badge-warning" - prettyStatus = "Unknown" + iconClass = "fa fa-question-circle"; + badgeClass = "badge badge-pill badge-warning"; + prettyStatus = "Unknown"; } const tooltip = ( -

Status: {prettyStatus}

- {props.data.get("error") !== "" && -

Error: {props.data.get("error")}

- } +

+ Status: {prettyStatus} +

+ {props.data.get("error") !== "" && ( +

Error: {props.data.get("error")}

+ )}
); @@ -125,7 +119,7 @@ const Module = (props) => { ); -} -Module.propTypes = { - data: PropTypes.instanceOf(Map), +}; +Module.propTypes = { + data: PropTypes.instanceOf(Map) }; diff --git a/frontend/js/components/movies/list.js b/frontend/js/components/movies/list.js index dbb3674..4389518 100644 --- a/frontend/js/components/movies/list.js +++ b/frontend/js/components/movies/list.js @@ -1,38 +1,43 @@ -import React from "react" -import PropTypes from "prop-types" -import { OrderedMap, Map } from "immutable" -import { connect } from "react-redux" -import { selectMovie, updateFilter, movieWishlistToggle } from "../../actions/movies" +import React from "react"; +import PropTypes from "prop-types"; +import { OrderedMap, Map } from "immutable"; +import { connect } from "react-redux"; +import { + selectMovie, + updateFilter, + movieWishlistToggle +} from "../../actions/movies"; -import ListDetails from "../list/details" -import ListPosters from "../list/posters" +import ListDetails from "../list/details"; +import ListPosters from "../list/posters"; -import { inLibrary, isWishlisted } from "../../utils" +import { inLibrary, isWishlisted } from "../../utils"; -import { ShowMore } from "../buttons/showMore" +import { ShowMore } from "../buttons/showMore"; -import { MovieSubtitlesButton } from "./subtitlesButton" -import { MovieTorrentsButton } from "./torrentsButton" +import { MovieSubtitlesButton } from "./subtitlesButton"; +import { MovieTorrentsButton } from "./torrentsButton"; function mapStateToProps(state) { return { - loading : state.movieStore.get("loading"), - movies : state.movieStore.get("movies"), - filter : state.movieStore.get("filter"), - selectedImdbId : state.movieStore.get("selectedImdbId"), - exploreOptions : state.movieStore.get("exploreOptions"), + loading: state.movieStore.get("loading"), + movies: state.movieStore.get("movies"), + filter: state.movieStore.get("filter"), + selectedImdbId: state.movieStore.get("selectedImdbId"), + exploreOptions: state.movieStore.get("exploreOptions") }; } const mapDispatchToProps = { - selectMovie, updateFilter, movieWishlistToggle, + selectMovie, + updateFilter, + movieWishlistToggle }; -const MovieList = (props) => { +const MovieList = props => { let selectedMovie = Map(); - if (props.movies !== undefined && - props.movies.has(props.selectedImdbId)) { - selectedMovie = props.movies.get(props.selectedImdbId); - } + if (props.movies !== undefined && props.movies.has(props.selectedImdbId)) { + selectedMovie = props.movies.get(props.selectedImdbId); + } return (
@@ -45,15 +50,24 @@ const MovieList = (props) => { updateFilter={props.updateFilter} filter={props.filter} onClick={props.selectMovie} - onDoubleClick={function() { return; }} - onKeyEnter={function() { return; }} + onDoubleClick={function() { + return; + }} + onKeyEnter={function() { + return; + }} params={props.match.params} loading={props.loading} /> props.movieWishlistToggle(selectedMovie.get("imdb_id"), isWishlisted(selectedMovie))} + wishlist={() => + props.movieWishlistToggle( + selectedMovie.get("imdb_id"), + isWishlisted(selectedMovie) + ) + } > {
); -} +}; MovieList.propTypes = { movies: PropTypes.instanceOf(OrderedMap), exploreOptions: PropTypes.instanceOf(Map), @@ -85,7 +99,7 @@ MovieList.propTypes = { updateFilter: PropTypes.func, movieWishlistToggle: PropTypes.func, selectMovie: PropTypes.func, - match: PropTypes.object, + match: PropTypes.object }; export default connect(mapStateToProps, mapDispatchToProps)(MovieList); diff --git a/frontend/js/components/movies/route.js b/frontend/js/components/movies/route.js index 0711ae5..7a10448 100644 --- a/frontend/js/components/movies/route.js +++ b/frontend/js/components/movies/route.js @@ -1,11 +1,11 @@ -import React from "react" -import PropTypes from "prop-types" -import { Route } from "react-router-dom" -import { connect } from "react-redux" -import { fetchMovies, getMovieExploreOptions } from "../../actions/movies" +import React from "react"; +import PropTypes from "prop-types"; +import { Route } from "react-router-dom"; +import { connect } from "react-redux"; +import { fetchMovies, getMovieExploreOptions } from "../../actions/movies"; -const mapStateToProps = (state) => ({ - isExplorerFetched: (state.movieStore.get("exploreOptions").size !== 0) +const mapStateToProps = state => ({ + isExplorerFetched: state.movieStore.get("exploreOptions").size !== 0 }); const mapDispatchToProps = { fetchMovies, getMovieExploreOptions }; @@ -17,44 +17,49 @@ const MoviesRoute = ({ ...otherProps }) => { return ( - { - let fetchUrl = ""; - switch (props.match.path) { - case "/movies/polochon": - fetchUrl = "/movies/polochon"; - break; - case "/movies/wishlist": - fetchUrl = "/wishlist/movies"; - break; - case "/movies/search/:search": - fetchUrl = "/movies/search/" + props.match.params.search; - break; - case "/movies/explore/:source/:category": - if (!isExplorerFetched) { - getMovieExploreOptions(); - } - fetchUrl = "/movies/explore?source=" + - encodeURI(props.match.params.source) + - "&category=" + encodeURI(props.match.params.category); - break; - default: - break; - } + { + let fetchUrl = ""; + switch (props.match.path) { + case "/movies/polochon": + fetchUrl = "/movies/polochon"; + break; + case "/movies/wishlist": + fetchUrl = "/wishlist/movies"; + break; + case "/movies/search/:search": + fetchUrl = "/movies/search/" + props.match.params.search; + break; + case "/movies/explore/:source/:category": + if (!isExplorerFetched) { + getMovieExploreOptions(); + } + fetchUrl = + "/movies/explore?source=" + + encodeURI(props.match.params.source) + + "&category=" + + encodeURI(props.match.params.category); + break; + default: + break; + } - if (fetchUrl != "") { - fetchMovies(fetchUrl); - } + if (fetchUrl != "") { + fetchMovies(fetchUrl); + } - return - }} /> - ) -} + return ; + }} + /> + ); +}; MoviesRoute.propTypes = { component: PropTypes.func, match: PropTypes.object, isExplorerFetched: PropTypes.bool.isRequired, fetchMovies: PropTypes.func.isRequired, - getMovieExploreOptions: PropTypes.func.isRequired, + getMovieExploreOptions: PropTypes.func.isRequired }; export default connect(mapStateToProps, mapDispatchToProps)(MoviesRoute); diff --git a/frontend/js/components/movies/subtitlesButton.js b/frontend/js/components/movies/subtitlesButton.js index c76fb65..496cddf 100644 --- a/frontend/js/components/movies/subtitlesButton.js +++ b/frontend/js/components/movies/subtitlesButton.js @@ -1,18 +1,18 @@ -import React from "react" -import PropTypes from "prop-types" -import { List } from "immutable" -import { connect } from "react-redux" +import React from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; +import { connect } from "react-redux"; -import { searchMovieSubtitles } from "../../actions/subtitles" +import { searchMovieSubtitles } from "../../actions/subtitles"; -import { SubtitlesButton } from "../buttons/subtitles" +import { SubtitlesButton } from "../buttons/subtitles"; const movieSubtitlesButton = ({ inLibrary, imdbId, searching, searchMovieSubtitles, - subtitles, + subtitles }) => ( searchMovieSubtitles(imdbId)} /> -) +); movieSubtitlesButton.propTypes = { searching: PropTypes.bool, inLibrary: PropTypes.bool, imdbId: PropTypes.string, searchMovieSubtitles: PropTypes.func, - subtitles: PropTypes.instanceOf(List), -} + subtitles: PropTypes.instanceOf(List) +}; -export const MovieSubtitlesButton = connect(null, {searchMovieSubtitles})(movieSubtitlesButton); +export const MovieSubtitlesButton = connect(null, { searchMovieSubtitles })( + movieSubtitlesButton +); diff --git a/frontend/js/components/movies/torrentsButton.js b/frontend/js/components/movies/torrentsButton.js index 0c3bcea..bd92b61 100644 --- a/frontend/js/components/movies/torrentsButton.js +++ b/frontend/js/components/movies/torrentsButton.js @@ -1,31 +1,33 @@ -import React from "react" -import PropTypes from "prop-types" -import { List } from "immutable" -import { connect } from "react-redux" +import React from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; +import { connect } from "react-redux"; -import { getMovieDetails } from "../../actions/movies" -import { TorrentsButton } from "../buttons/torrents" +import { getMovieDetails } from "../../actions/movies"; +import { TorrentsButton } from "../buttons/torrents"; const movieTorrentsButton = ({ torrents, imdbId, title, searching, - getMovieDetails, + getMovieDetails }) => ( getMovieDetails(imdbId)} url={`#/torrents/search/movies/${encodeURI(title)}`} - /> -) + /> +); movieTorrentsButton.propTypes = { torrents: PropTypes.instanceOf(List), imdbId: PropTypes.string, title: PropTypes.string, searching: PropTypes.bool, - getMovieDetails: PropTypes.func, + getMovieDetails: PropTypes.func }; -export const MovieTorrentsButton = connect(null, {getMovieDetails})(movieTorrentsButton); +export const MovieTorrentsButton = connect(null, { getMovieDetails })( + movieTorrentsButton +); diff --git a/frontend/js/components/navbar.js b/frontend/js/components/navbar.js index aa3c798..7d421ee 100644 --- a/frontend/js/components/navbar.js +++ b/frontend/js/components/navbar.js @@ -1,31 +1,41 @@ -import React, { useState } from "react" -import { Route } from "react-router-dom" -import { connect } from "react-redux" -import { LinkContainer } from "react-router-bootstrap" -import PropTypes from "prop-types" +import React, { useState } from "react"; +import { Route } from "react-router-dom"; +import { connect } from "react-redux"; +import { LinkContainer } from "react-router-bootstrap"; +import PropTypes from "prop-types"; -import Nav from "react-bootstrap/Nav" -import Navbar from "react-bootstrap/Navbar" -import NavDropdown from "react-bootstrap/NavDropdown" +import Nav from "react-bootstrap/Nav"; +import Navbar from "react-bootstrap/Navbar"; +import NavDropdown from "react-bootstrap/NavDropdown"; -const mapStateToProps = (state) => { +const mapStateToProps = state => { let torrentCount = 0; - if (state.torrentStore.has("torrents") && state.torrentStore.get("torrents") !== undefined) { + if ( + state.torrentStore.has("torrents") && + state.torrentStore.get("torrents") !== undefined + ) { torrentCount = state.torrentStore.get("torrents").size; } return { username: state.userStore.get("username"), isAdmin: state.userStore.get("isAdmin"), - torrentCount: torrentCount, - } + torrentCount: torrentCount + }; }; -const AppNavBar = (props) => { +const AppNavBar = props => { const [expanded, setExpanded] = useState(false); return ( - setExpanded(!expanded)}> + setExpanded(!expanded)} + > Canapé @@ -38,36 +48,39 @@ const AppNavBar = (props) => { ); -} +}; AppNavBar.propTypes = { torrentCount: PropTypes.number.isRequired, username: PropTypes.string.isRequired, isAdmin: PropTypes.bool.isRequired, - history: PropTypes.object, + history: PropTypes.object }; export default connect(mapStateToProps)(AppNavBar); @@ -75,30 +88,30 @@ export default connect(mapStateToProps)(AppNavBar); const Search = ({ path, placeholder, setExpanded, history }) => { const [search, setSearch] = useState(""); - const handleSearch = (ev) => { + const handleSearch = ev => { ev.preventDefault(); history.push(`${path}/${encodeURI(search)}`); setExpanded(false); - } + }; - return( + return (
-
handleSearch(ev)}> + handleSearch(ev)}> setSearch(e.target.value)} + onChange={e => setSearch(e.target.value)} />
); -} +}; Search.propTypes = { placeholder: PropTypes.string.isRequired, setExpanded: PropTypes.func.isRequired, path: PropTypes.string.isRequired, - history: PropTypes.object, + history: PropTypes.object }; const MoviesDropdown = () => ( @@ -110,7 +123,7 @@ const MoviesDropdown = () => ( My movies -) +); const ShowsDropdown = () => ( @@ -123,14 +136,14 @@ const ShowsDropdown = () => ( ); -const UserDropdown = (props) => ( +const UserDropdown = props => ( -) +); UserDropdown.propTypes = { username: PropTypes.string.isRequired, - isAdmin: PropTypes.bool.isRequired, + isAdmin: PropTypes.bool.isRequired }; const WishlistDropdown = () => ( @@ -159,9 +172,9 @@ const WishlistDropdown = () => ( ); -const TorrentsDropdown = (props) => { - const title = () - return( +const TorrentsDropdown = props => { + const title = ; + return ( Downloads @@ -171,22 +184,27 @@ const TorrentsDropdown = (props) => { ); -} +}; TorrentsDropdown.propTypes = { torrentsCount: PropTypes.number.isRequired }; -const TorrentsDropdownTitle = (props) => { +const TorrentsDropdownTitle = props => { if (props.torrentsCount === 0) { - return ( - Torrents - ); + return Torrents; } return ( - Torrents + + {" "} + Torrents -   {props.torrentsCount} +  {" "} + + {props.torrentsCount} + ); -} -TorrentsDropdownTitle.propTypes = { torrentsCount: PropTypes.number.isRequired }; +}; +TorrentsDropdownTitle.propTypes = { + torrentsCount: PropTypes.number.isRequired +}; diff --git a/frontend/js/components/notifications/notification.js b/frontend/js/components/notifications/notification.js index dc82fb9..cb69e46 100644 --- a/frontend/js/components/notifications/notification.js +++ b/frontend/js/components/notifications/notification.js @@ -1,10 +1,10 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; -import { Toast } from "react-bootstrap" +import { Toast } from "react-bootstrap"; -import { removeNotification } from "../../actions/notifications" +import { removeNotification } from "../../actions/notifications"; const NotificationConnected = ({ id, @@ -14,39 +14,30 @@ const NotificationConnected = ({ imageUrl, autohide, delay, - removeNotification, + removeNotification }) => { - const [show, setShow] = useState(true) + const [show, setShow] = useState(true); const hide = () => { setShow(false); setTimeout(() => removeNotification(id), 200); - } + }; return ( - + - {icon !== "" && - - } + {icon !== "" && } {title} - {message !== "" && - {message} - } - {imageUrl !== "" && - - } + {message !== "" && {message}} + {imageUrl !== "" && ( + + )} - ) -} + ); +}; NotificationConnected.propTypes = { id: PropTypes.string, icon: PropTypes.string, @@ -55,7 +46,7 @@ NotificationConnected.propTypes = { imageUrl: PropTypes.string, autohide: PropTypes.bool, delay: PropTypes.number, - removeNotification: PropTypes.func, + removeNotification: PropTypes.func }; NotificationConnected.defaultProps = { @@ -64,7 +55,9 @@ NotificationConnected.defaultProps = { icon: "", imageUrl: "", title: "Info", - message: "", + message: "" }; -export const Notification = connect(null, {removeNotification})(NotificationConnected); +export const Notification = connect(null, { removeNotification })( + NotificationConnected +); diff --git a/frontend/js/components/notifications/notifications.js b/frontend/js/components/notifications/notifications.js index 179a24a..d8d6447 100644 --- a/frontend/js/components/notifications/notifications.js +++ b/frontend/js/components/notifications/notifications.js @@ -1,14 +1,14 @@ -import React from "react" -import PropTypes from "prop-types" -import { List } from "immutable" -import { connect } from "react-redux" +import React from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; +import { connect } from "react-redux"; -import { Notification } from "./notification" +import { Notification } from "./notification"; const NotificationsConnected = ({ notifications }) => { return (
- {notifications.map((el) => ( + {notifications.map(el => ( { /> ))}
- ) -} + ); +}; NotificationsConnected.propTypes = { - notifications: PropTypes.instanceOf(List), -} + notifications: PropTypes.instanceOf(List) +}; -const mapStateToProps = (state) => ({ - notifications: state.notifications, +const mapStateToProps = state => ({ + notifications: state.notifications }); export const Notifications = connect(mapStateToProps)(NotificationsConnected); diff --git a/frontend/js/components/polochons/add.js b/frontend/js/components/polochons/add.js index e2cf7f7..6fab15c 100644 --- a/frontend/js/components/polochons/add.js +++ b/frontend/js/components/polochons/add.js @@ -1,10 +1,10 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; -import { addPolochon } from "../../actions/polochon" +import { addPolochon } from "../../actions/polochon"; -import { PolochonEdit } from "./edit" +import { PolochonEdit } from "./edit"; export const PolochonAddConnected = ({ addPolochon }) => { const [modal, setModal] = useState(false); @@ -24,10 +24,10 @@ export const PolochonAddConnected = ({ addPolochon }) => { update={addPolochon} /> - ) -} + ); +}; PolochonAddConnected.propTypes = { - addPolochon: PropTypes.func, + addPolochon: PropTypes.func }; -export const PolochonAdd = connect(null, {addPolochon})(PolochonAddConnected); +export const PolochonAdd = connect(null, { addPolochon })(PolochonAddConnected); diff --git a/frontend/js/components/polochons/edit.js b/frontend/js/components/polochons/edit.js index a09a5f5..6f7e5a5 100644 --- a/frontend/js/components/polochons/edit.js +++ b/frontend/js/components/polochons/edit.js @@ -1,8 +1,8 @@ -import React, { useState, useEffect } from "react" -import PropTypes from "prop-types" +import React, { useState, useEffect } from "react"; +import PropTypes from "prop-types"; -import { FormModal } from "../forms/modal" -import { FormInput } from "../forms/input" +import { FormModal } from "../forms/modal"; +import { FormInput } from "../forms/input"; export const PolochonEdit = ({ show, @@ -13,7 +13,7 @@ export const PolochonEdit = ({ initialName, initialUrl, initialToken, - update, + update }) => { const [name, setName] = useState(initialName); const [url, setUrl] = useState(initialUrl); @@ -23,7 +23,7 @@ export const PolochonEdit = ({ setName(initialName); setUrl(initialUrl); setToken(initialToken); - }, [id, initialName, initialUrl, initialToken]) + }, [id, initialName, initialUrl, initialToken]); const handleSubmit = () => { update({ id, name, url, token }); @@ -42,8 +42,8 @@ export const PolochonEdit = ({ - ) -} + ); +}; PolochonEdit.propTypes = { show: PropTypes.bool, title: PropTypes.string, @@ -53,7 +53,7 @@ PolochonEdit.propTypes = { id: PropTypes.string, initialName: PropTypes.string, initialUrl: PropTypes.string, - initialToken: PropTypes.string, + initialToken: PropTypes.string }; PolochonEdit.defaultProps = { id: "", @@ -61,5 +61,5 @@ PolochonEdit.defaultProps = { icon: "edit", initialName: "", initialUrl: "", - initialToken: "", + initialToken: "" }; diff --git a/frontend/js/components/polochons/list.js b/frontend/js/components/polochons/list.js index 1319140..1a3dea1 100644 --- a/frontend/js/components/polochons/list.js +++ b/frontend/js/components/polochons/list.js @@ -1,29 +1,25 @@ -import React, { useEffect } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import { List } from "immutable" +import React, { useEffect } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { List } from "immutable"; -import { getManagedPolochons } from "../../actions/polochon" +import { getManagedPolochons } from "../../actions/polochon"; -import { Polochon } from "./polochon" -import { PolochonAdd } from "./add" +import { Polochon } from "./polochon"; +import { PolochonAdd } from "./add"; -const mapStateToProps = (state) => ({ - managedList: state.polochon.get("managed"), +const mapStateToProps = state => ({ + managedList: state.polochon.get("managed") }); const mapDispatchToProps = { - getManagedPolochons, -} - -const PolochonListConnected = ({ - getManagedPolochons, - managedList, -}) => { + getManagedPolochons +}; +const PolochonListConnected = ({ getManagedPolochons, managedList }) => { useEffect(() => { getManagedPolochons(); - }, [getManagedPolochons]) + }, [getManagedPolochons]); return (
@@ -46,11 +42,14 @@ const PolochonListConnected = ({
- ) -} + ); +}; PolochonListConnected.propTypes = { getManagedPolochons: PropTypes.func, - managedList: PropTypes.instanceOf(List), + managedList: PropTypes.instanceOf(List) }; -export const PolochonList = connect(mapStateToProps, mapDispatchToProps)(PolochonListConnected); +export const PolochonList = connect( + mapStateToProps, + mapDispatchToProps +)(PolochonListConnected); diff --git a/frontend/js/components/polochons/polochon.js b/frontend/js/components/polochons/polochon.js index 7efb43c..6ad0c49 100644 --- a/frontend/js/components/polochons/polochon.js +++ b/frontend/js/components/polochons/polochon.js @@ -1,12 +1,12 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { List } from "immutable" -import { connect } from "react-redux" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; +import { connect } from "react-redux"; -import { PolochonUsers } from "./users" -import { PolochonEdit } from "./edit" +import { PolochonUsers } from "./users"; +import { PolochonEdit } from "./edit"; -import { updatePolochon, deletePolochon } from "../../actions/polochon" +import { updatePolochon, deletePolochon } from "../../actions/polochon"; export const PolochonConnected = ({ id, @@ -16,7 +16,7 @@ export const PolochonConnected = ({ authToken, users, updatePolochon, - deletePolochon, + deletePolochon }) => { const [edit, setEdit] = useState(false); @@ -25,9 +25,7 @@ export const PolochonConnected = ({
{name !== "" ? name : "-"} - - ({url !== "" ? url : "-"}) - + ({url !== "" ? url : "-"}) - ) -} + ); +}; PolochonConnected.propTypes = { id: PropTypes.string, name: PropTypes.string, @@ -68,7 +66,9 @@ PolochonConnected.propTypes = { authToken: PropTypes.string, users: PropTypes.instanceOf(List), updatePolochon: PropTypes.func, - deletePolochon: PropTypes.func, + deletePolochon: PropTypes.func }; -export const Polochon = connect(null, { updatePolochon, deletePolochon })(PolochonConnected); +export const Polochon = connect(null, { updatePolochon, deletePolochon })( + PolochonConnected +); diff --git a/frontend/js/components/polochons/select.js b/frontend/js/components/polochons/select.js index b3fe9a6..1ecbf79 100644 --- a/frontend/js/components/polochons/select.js +++ b/frontend/js/components/polochons/select.js @@ -1,30 +1,26 @@ -import React from "react" -import PropTypes from "prop-types" -import { List } from "immutable" +import React from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; -export const PolochonSelect = ({ - value, - changeValue, - polochonList, -}) => { +export const PolochonSelect = ({ value, changeValue, polochonList }) => { return ( ); -} +}; PolochonSelect.propTypes = { value: PropTypes.string, changeValue: PropTypes.func, - polochonList: PropTypes.instanceOf(List), + polochonList: PropTypes.instanceOf(List) }; diff --git a/frontend/js/components/polochons/user.js b/frontend/js/components/polochons/user.js index fd86740..c1a7b37 100644 --- a/frontend/js/components/polochons/user.js +++ b/frontend/js/components/polochons/user.js @@ -1,13 +1,13 @@ -import React, { useState, useEffect } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" +import React, { useState, useEffect } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; -import { editPolochonUser } from "../../actions/polochon" +import { editPolochonUser } from "../../actions/polochon"; import Toggle from "react-bootstrap-toggle"; -import { FormModal } from "../forms/modal" -import { FormInput } from "../forms/input" +import { FormModal } from "../forms/modal"; +import { FormInput } from "../forms/input"; export const PolochonUserConnected = ({ polochonId, @@ -15,7 +15,7 @@ export const PolochonUserConnected = ({ name, initialToken, initialActivated, - editPolochonUser, + editPolochonUser }) => { const [edit, setEdit] = useState(false); const [token, setToken] = useState(initialToken); @@ -24,26 +24,22 @@ export const PolochonUserConnected = ({ useEffect(() => { setActivated(initialActivated); setToken(initialToken); - }, [initialActivated, initialToken]) + }, [initialActivated, initialToken]); const handleSubmit = () => { editPolochonUser({ polochonId, id, token, - activated, + activated }); setEdit(false); - } + }; return ( - - {name} - - - {activated ? "Activated" : "Not activated"} - + {name} + {activated ? "Activated" : "Not activated"} setEdit(true)} /> setActivated(!activated)} /> + onClick={() => setActivated(!activated)} + />
- ) -} + ); +}; PolochonUserConnected.propTypes = { polochonId: PropTypes.string, id: PropTypes.string, name: PropTypes.string, initialToken: PropTypes.string, initialActivated: PropTypes.bool, - editPolochonUser: PropTypes.func, + editPolochonUser: PropTypes.func }; -export const PolochonUser = connect(null, {editPolochonUser})(PolochonUserConnected); +export const PolochonUser = connect(null, { editPolochonUser })( + PolochonUserConnected +); diff --git a/frontend/js/components/polochons/users.js b/frontend/js/components/polochons/users.js index 3dba984..d43320b 100644 --- a/frontend/js/components/polochons/users.js +++ b/frontend/js/components/polochons/users.js @@ -1,11 +1,13 @@ -import React from "react" -import PropTypes from "prop-types" -import { List } from "immutable" +import React from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; -import { PolochonUser } from "./user" +import { PolochonUser } from "./user"; export const PolochonUsers = ({ id, users }) => { - if (users === null || users.size === 0) { return null } + if (users === null || users.size === 0) { + return null; + } return ( @@ -29,9 +31,9 @@ export const PolochonUsers = ({ id, users }) => { ))}
- ) -} + ); +}; PolochonUsers.propTypes = { id: PropTypes.string, - users: PropTypes.instanceOf(List), + users: PropTypes.instanceOf(List) }; diff --git a/frontend/js/components/shows/details.js b/frontend/js/components/shows/details.js index ca988a7..a99acf4 100644 --- a/frontend/js/components/shows/details.js +++ b/frontend/js/components/shows/details.js @@ -1,22 +1,22 @@ -import React from "react" -import PropTypes from "prop-types" -import { Map } from "immutable" -import { connect } from "react-redux" +import React from "react"; +import PropTypes from "prop-types"; +import { Map } from "immutable"; +import { connect } from "react-redux"; -import Loader from "../loader/loader" +import Loader from "../loader/loader"; -import { Fanart } from "./details/fanart" -import { Header } from "./details/header" -import { SeasonsList } from "./details/seasons" +import { Fanart } from "./details/fanart"; +import { Header } from "./details/header"; +import { SeasonsList } from "./details/seasons"; -const mapStateToProps = (state) => ({ +const mapStateToProps = state => ({ loading: state.showStore.get("loading"), - show: state.showStore.get("show"), -}) + show: state.showStore.get("show") +}); const showDetails = ({ show, loading }) => { if (loading === true) { - return (); + return ; } return ( @@ -28,9 +28,9 @@ const showDetails = ({ show, loading }) => {
); -} +}; showDetails.propTypes = { loading: PropTypes.bool, - show: PropTypes.instanceOf(Map), + show: PropTypes.instanceOf(Map) }; export const ShowDetails = connect(mapStateToProps)(showDetails); diff --git a/frontend/js/components/shows/details/episode.js b/frontend/js/components/shows/details/episode.js index ef15257..42ab9e7 100644 --- a/frontend/js/components/shows/details/episode.js +++ b/frontend/js/components/shows/details/episode.js @@ -1,31 +1,35 @@ -import React from "react" -import PropTypes from "prop-types" -import { Map } from "immutable" -import { connect } from "react-redux" +import React from "react"; +import PropTypes from "prop-types"; +import { Map } from "immutable"; +import { connect } from "react-redux"; -import { showWishlistToggle } from "../../../actions/shows" +import { showWishlistToggle } from "../../../actions/shows"; -import { inLibrary, isEpisodeWishlisted, prettyEpisodeName } from "../../../utils" +import { + inLibrary, + isEpisodeWishlisted, + prettyEpisodeName +} from "../../../utils"; -import { Plot } from "../../details/plot" -import { PolochonMetadata } from "../../details/polochon" -import { ReleaseDate } from "../../details/releaseDate" -import { Runtime } from "../../details/runtime" -import { Title } from "../../details/title" +import { Plot } from "../../details/plot"; +import { PolochonMetadata } from "../../details/polochon"; +import { ReleaseDate } from "../../details/releaseDate"; +import { Runtime } from "../../details/runtime"; +import { Title } from "../../details/title"; -import { DownloadAndStream } from "../../buttons/download" -import { ShowMore } from "../../buttons/showMore" +import { DownloadAndStream } from "../../buttons/download"; +import { ShowMore } from "../../buttons/showMore"; -import { EpisodeSubtitlesButton } from "./subtitlesButton" -import { EpisodeThumb } from "./episodeThumb" -import { EpisodeTorrentsButton } from "./torrentsButton" +import { EpisodeSubtitlesButton } from "./subtitlesButton"; +import { EpisodeThumb } from "./episodeThumb"; +import { EpisodeTorrentsButton } from "./torrentsButton"; -const mapStateToProps = (state) => ({ +const mapStateToProps = state => ({ trackedSeason: state.showStore.getIn(["show", "tracked_season"], null), - trackedEpisode: state.showStore.getIn(["show", "tracked_episode"], null), -}) + trackedEpisode: state.showStore.getIn(["show", "tracked_episode"], null) +}); -const episode = (props) => ( +const episode = props => (
@@ -34,20 +38,26 @@ const episode = (props) => ( wishlisted={isEpisodeWishlisted( props.data, props.trackedSeason, - props.trackedEpisode, - )} - wishlist={() => props.showWishlistToggle( - isEpisodeWishlisted(props.data), - props.data.get("show_imdb_id"), - props.data.get("season"), - props.data.get("episode"), + props.trackedEpisode )} + wishlist={() => + props.showWishlistToggle( + isEpisodeWishlisted(props.data), + props.data.get("show_imdb_id"), + props.data.get("season"), + props.data.get("episode") + ) + } /> @@ -60,7 +70,11 @@ const episode = (props) => ( light /> (
-) +); episode.propTypes = { data: PropTypes.instanceOf(Map).isRequired, trackedSeason: PropTypes.number, trackedEpisode: PropTypes.number, showName: PropTypes.string.isRequired, - showWishlistToggle: PropTypes.func, + showWishlistToggle: PropTypes.func }; -export const Episode = connect(mapStateToProps, {showWishlistToggle})(episode); +export const Episode = connect(mapStateToProps, { showWishlistToggle })( + episode +); diff --git a/frontend/js/components/shows/details/episodeThumb.js b/frontend/js/components/shows/details/episodeThumb.js index 435c017..26a5e71 100644 --- a/frontend/js/components/shows/details/episodeThumb.js +++ b/frontend/js/components/shows/details/episodeThumb.js @@ -1,13 +1,15 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; export const EpisodeThumb = ({ url }) => { - if (url === "") { return null } + if (url === "") { + return null; + } return (
- ) -} + ); +}; EpisodeThumb.propTypes = { url: PropTypes.string }; EpisodeThumb.defaultProps = { url: "" }; diff --git a/frontend/js/components/shows/details/fanart.js b/frontend/js/components/shows/details/fanart.js index b1cb153..b4eecbe 100644 --- a/frontend/js/components/shows/details/fanart.js +++ b/frontend/js/components/shows/details/fanart.js @@ -1,5 +1,5 @@ -import React from "react" -import PropTypes from "prop-types" +import React from "react"; +import PropTypes from "prop-types"; export const Fanart = ({ url }) => (
@@ -8,7 +8,7 @@ export const Fanart = ({ url }) => ( src={url} />
-) +); Fanart.propTypes = { - url: PropTypes.string, -} + url: PropTypes.string +}; diff --git a/frontend/js/components/shows/details/header.js b/frontend/js/components/shows/details/header.js index b17b71c..42f3251 100644 --- a/frontend/js/components/shows/details/header.js +++ b/frontend/js/components/shows/details/header.js @@ -1,21 +1,21 @@ -import React from "react" -import PropTypes from "prop-types" -import { Map } from "immutable" -import { connect } from "react-redux" +import React from "react"; +import PropTypes from "prop-types"; +import { Map } from "immutable"; +import { connect } from "react-redux"; -import { isWishlisted } from "../../../utils" +import { isWishlisted } from "../../../utils"; -import { showWishlistToggle } from "../../../actions/shows" +import { showWishlistToggle } from "../../../actions/shows"; -import { Plot } from "../../details/plot" -import { Rating } from "../../details/rating" -import { ReleaseDate } from "../../details/releaseDate" -import { Title } from "../../details/title" -import { TrackingLabel } from "../../details/tracking" +import { Plot } from "../../details/plot"; +import { Rating } from "../../details/rating"; +import { ReleaseDate } from "../../details/releaseDate"; +import { Title } from "../../details/title"; +import { TrackingLabel } from "../../details/tracking"; -import { ImdbBadge } from "../../buttons/imdb" +import { ImdbBadge } from "../../buttons/imdb"; -export const header = (props) => ( +export const header = props => (
@@ -30,9 +30,12 @@ export const header = (props) => ( props.showWishlistToggle( - isWishlisted(props.data), props.data.get("imdb_id"), - )} + wishlist={() => + props.showWishlistToggle( + isWishlisted(props.data), + props.data.get("imdb_id") + ) + } /> </p> <p className="card-text"> @@ -61,7 +64,7 @@ export const header = (props) => ( ); header.propTypes = { data: PropTypes.instanceOf(Map), - showWishlistToggle: PropTypes.func, + showWishlistToggle: PropTypes.func }; -export const Header = connect(null, {showWishlistToggle})(header); +export const Header = connect(null, { showWishlistToggle })(header); diff --git a/frontend/js/components/shows/details/season.js b/frontend/js/components/shows/details/season.js index 918e27e..bd933a3 100644 --- a/frontend/js/components/shows/details/season.js +++ b/frontend/js/components/shows/details/season.js @@ -1,10 +1,10 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { Map } from "immutable" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { Map } from "immutable"; -import { Episode } from "./episode" +import { Episode } from "./episode"; -export const Season = (props) => { +export const Season = props => { const [show, setShow] = useState(false); return ( @@ -12,8 +12,13 @@ export const Season = (props) => { <div className="card-header clickable" onClick={() => setShow(!show)}> <h5 className="m-0"> Season {props.season} - <small className="text-primary"> — ({props.data.toList().size} episodes)</small> - <i className={`float-right fa fa-chevron-${show ? "down" : "left"}`}></i> + <small className="text-primary"> + {" "} + — ({props.data.toList().size} episodes) + </small> + <i + className={`float-right fa fa-chevron-${show ? "down" : "left"}`} + ></i> </h5> </div> <div className={`card-body ${show ? "d-flex flex-column" : "d-none"}`}> @@ -29,12 +34,12 @@ export const Season = (props) => { getEpisodeDetails={props.getEpisodeDetails} refreshSubtitles={props.refreshSubtitles} /> - ) + ); })} </div> </div> - ) -} + ); +}; Season.propTypes = { data: PropTypes.instanceOf(Map), season: PropTypes.number, @@ -42,5 +47,5 @@ Season.propTypes = { addToWishlist: PropTypes.func, addTorrent: PropTypes.func, refreshSubtitles: PropTypes.func, - getEpisodeDetails: PropTypes.func, + getEpisodeDetails: PropTypes.func }; diff --git a/frontend/js/components/shows/details/seasons.js b/frontend/js/components/shows/details/seasons.js index 5b676bb..ac52e5b 100644 --- a/frontend/js/components/shows/details/seasons.js +++ b/frontend/js/components/shows/details/seasons.js @@ -1,26 +1,31 @@ -import React from "react" -import PropTypes from "prop-types" -import { Map } from "immutable" +import React from "react"; +import PropTypes from "prop-types"; +import { Map } from "immutable"; -import { Season } from "./season" +import { Season } from "./season"; -export const SeasonsList = (props) => ( +export const SeasonsList = props => ( <div className="col col-12 col-md-10 offset-md-1"> - {props.data.get("seasons").entrySeq().map(function([season, data]) { - if (season === 0) { return null } - return ( - <Season - key={`season-list-key-${season}`} - data={data} - season={season} - showName={props.data.get("title")} - addTorrent={props.addTorrent} - addToWishlist={props.addToWishlist} - getEpisodeDetails={props.getEpisodeDetails} - refreshSubtitles={props.refreshSubtitles} - /> - ); - })} + {props.data + .get("seasons") + .entrySeq() + .map(function([season, data]) { + if (season === 0) { + return null; + } + return ( + <Season + key={`season-list-key-${season}`} + data={data} + season={season} + showName={props.data.get("title")} + addTorrent={props.addTorrent} + addToWishlist={props.addToWishlist} + getEpisodeDetails={props.getEpisodeDetails} + refreshSubtitles={props.refreshSubtitles} + /> + ); + })} </div> ); SeasonsList.propTypes = { @@ -28,5 +33,5 @@ SeasonsList.propTypes = { addToWishlist: PropTypes.func, addTorrent: PropTypes.func, refreshSubtitles: PropTypes.func, - getEpisodeDetails: PropTypes.func, + getEpisodeDetails: PropTypes.func }; diff --git a/frontend/js/components/shows/details/subtitlesButton.js b/frontend/js/components/shows/details/subtitlesButton.js index 70cad7e..3a9cf80 100644 --- a/frontend/js/components/shows/details/subtitlesButton.js +++ b/frontend/js/components/shows/details/subtitlesButton.js @@ -1,11 +1,11 @@ -import React from "react" -import PropTypes from "prop-types" -import { List } from "immutable" -import { connect } from "react-redux" +import React from "react"; +import PropTypes from "prop-types"; +import { List } from "immutable"; +import { connect } from "react-redux"; -import { searchEpisodeSubtitles } from "../../../actions/subtitles" +import { searchEpisodeSubtitles } from "../../../actions/subtitles"; -import { SubtitlesButton } from "../../buttons/subtitles" +import { SubtitlesButton } from "../../buttons/subtitles"; const episodeSubtitlesButton = ({ inLibrary, @@ -14,7 +14,7 @@ const episodeSubtitlesButton = ({ episode, searching, searchEpisodeSubtitles, - subtitles, + subtitles }) => ( <SubtitlesButton subtitles={subtitles} @@ -22,7 +22,7 @@ const episodeSubtitlesButton = ({ searching={searching} search={() => searchEpisodeSubtitles(imdbId, season, episode)} /> -) +); episodeSubtitlesButton.propTypes = { inLibrary: PropTypes.bool, @@ -31,7 +31,9 @@ episodeSubtitlesButton.propTypes = { season: PropTypes.number, episode: PropTypes.number, searchEpisodeSubtitles: PropTypes.func, - subtitles: PropTypes.instanceOf(List), -} + subtitles: PropTypes.instanceOf(List) +}; -export const EpisodeSubtitlesButton = connect(null, {searchEpisodeSubtitles})(episodeSubtitlesButton); +export const EpisodeSubtitlesButton = connect(null, { searchEpisodeSubtitles })( + episodeSubtitlesButton +); diff --git a/frontend/js/components/shows/details/torrentsButton.js b/frontend/js/components/shows/details/torrentsButton.js index bb21cf9..ab0f643 100644 --- a/frontend/js/components/shows/details/torrentsButton.js +++ b/frontend/js/components/shows/details/torrentsButton.js @@ -1,11 +1,11 @@ -import React from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import { List } from "immutable" +import React from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { List } from "immutable"; -import { getEpisodeDetails } from "../../../actions/shows" -import { TorrentsButton } from "../../buttons/torrents" -import { prettyEpisodeName } from "../../../utils" +import { getEpisodeDetails } from "../../../actions/shows"; +import { TorrentsButton } from "../../buttons/torrents"; +import { prettyEpisodeName } from "../../../utils"; const episodeTorrentsButton = ({ torrents, @@ -14,17 +14,17 @@ const episodeTorrentsButton = ({ episode, showName, searching, - getEpisodeDetails, + getEpisodeDetails }) => ( <TorrentsButton torrents={torrents} searching={searching} search={() => getEpisodeDetails(imdbId, season, episode)} - url={`#/torrents/search/shows/${ - encodeURI(prettyEpisodeName(showName, season, episode)) - }`} - /> -) + url={`#/torrents/search/shows/${encodeURI( + prettyEpisodeName(showName, season, episode) + )}`} + /> +); episodeTorrentsButton.propTypes = { torrents: PropTypes.instanceOf(List), showName: PropTypes.string.isRequired, @@ -32,7 +32,9 @@ episodeTorrentsButton.propTypes = { episode: PropTypes.number.isRequired, season: PropTypes.number.isRequired, searching: PropTypes.bool.isRequired, - getEpisodeDetails: PropTypes.func.isRequired, + getEpisodeDetails: PropTypes.func.isRequired }; -export const EpisodeTorrentsButton = connect(null, {getEpisodeDetails})(episodeTorrentsButton); +export const EpisodeTorrentsButton = connect(null, { getEpisodeDetails })( + episodeTorrentsButton +); diff --git a/frontend/js/components/shows/list.js b/frontend/js/components/shows/list.js index 2361f2c..c08e5b7 100644 --- a/frontend/js/components/shows/list.js +++ b/frontend/js/components/shows/list.js @@ -1,33 +1,39 @@ -import React from "react" -import PropTypes from "prop-types" -import { Map } from "immutable" -import { connect } from "react-redux" -import { selectShow, showWishlistToggle, - getShowDetails, updateFilter } from "../../actions/shows" +import React from "react"; +import PropTypes from "prop-types"; +import { Map } from "immutable"; +import { connect } from "react-redux"; +import { + selectShow, + showWishlistToggle, + getShowDetails, + updateFilter +} from "../../actions/shows"; -import { isWishlisted } from "../../utils" +import { isWishlisted } from "../../utils"; -import ListDetails from "../list/details" -import ListPosters from "../list/posters" +import ListDetails from "../list/details"; +import ListPosters from "../list/posters"; function mapStateToProps(state) { return { - loading : state.showsStore.get("loading"), - shows : state.showsStore.get("shows"), - filter : state.showsStore.get("filter"), - selectedImdbId : state.showsStore.get("selectedImdbId"), - exploreOptions : state.showsStore.get("exploreOptions"), + loading: state.showsStore.get("loading"), + shows: state.showsStore.get("shows"), + filter: state.showsStore.get("filter"), + selectedImdbId: state.showsStore.get("selectedImdbId"), + exploreOptions: state.showsStore.get("exploreOptions") }; } const mapDispatchToProps = { - selectShow, showWishlistToggle, - getShowDetails, updateFilter, + selectShow, + showWishlistToggle, + getShowDetails, + updateFilter }; -const ShowList = (props) => { - const showDetails = (imdbId) => { +const ShowList = props => { + const showDetails = imdbId => { props.history.push("/shows/details/" + imdbId); - } + }; let selectedShow = Map(); if (props.selectedImdbId !== "") { @@ -53,14 +59,18 @@ const ShowList = (props) => { <ListDetails data={selectedShow} loading={props.loading} - wishlist={() => props.showWishlistToggle( - isWishlisted(selectedShow), selectedShow.get("imdb_id"), - )} + wishlist={() => + props.showWishlistToggle( + isWishlisted(selectedShow), + selectedShow.get("imdb_id") + ) + } > <span> - <button onClick={ - () => showDetails(selectedShow.get("imdb_id"))} - className="btn btn-primary btn-sm w-md-100"> + <button + onClick={() => showDetails(selectedShow.get("imdb_id"))} + className="btn btn-primary btn-sm w-md-100" + > <i className="fa fa-external-link mr-1" /> Details </button> @@ -68,7 +78,7 @@ const ShowList = (props) => { </ListDetails> </div> ); -} +}; ShowList.propTypes = { match: PropTypes.object, history: PropTypes.object, @@ -80,6 +90,6 @@ ShowList.propTypes = { showWishlistToggle: PropTypes.func, selectShow: PropTypes.func, getShowDetails: PropTypes.func, - updateFilter: PropTypes.func, + updateFilter: PropTypes.func }; export default connect(mapStateToProps, mapDispatchToProps)(ShowList); diff --git a/frontend/js/components/shows/route.js b/frontend/js/components/shows/route.js index 18e5c9e..ed0d07e 100644 --- a/frontend/js/components/shows/route.js +++ b/frontend/js/components/shows/route.js @@ -1,13 +1,21 @@ -import React from "react" -import PropTypes from "prop-types" -import { Route } from "react-router-dom" -import { connect } from "react-redux" -import { fetchShows, fetchShowDetails, getShowExploreOptions } from "../../actions/shows" +import React from "react"; +import PropTypes from "prop-types"; +import { Route } from "react-router-dom"; +import { connect } from "react-redux"; +import { + fetchShows, + fetchShowDetails, + getShowExploreOptions +} from "../../actions/shows"; -const mapStateToProps = (state) => ({ - isExplorerFetched: (state.showsStore.get("exploreOptions").size !== 0) +const mapStateToProps = state => ({ + isExplorerFetched: state.showsStore.get("exploreOptions").size !== 0 }); -const mapDispatchToProps = { fetchShows, fetchShowDetails, getShowExploreOptions }; +const mapDispatchToProps = { + fetchShows, + fetchShowDetails, + getShowExploreOptions +}; const ShowsRoute = ({ component: Component, @@ -18,46 +26,51 @@ const ShowsRoute = ({ ...otherProps }) => { return ( - <Route {...otherProps} render={(props) => { - let fetchUrl = ""; - switch (props.match.path) { - case "/shows/polochon": - fetchUrl = "/shows/polochon"; - break; - case "/shows/wishlist": - fetchUrl = "/wishlist/shows"; - break; - case "/shows/search/:search": - fetchUrl = "/shows/search/" + props.match.params.search; - break; - case "/shows/explore/:source/:category": - if (!isExplorerFetched) { - getShowExploreOptions(); - } - fetchUrl = "/shows/explore?source=" + - encodeURI(props.match.params.source) + - "&category=" + encodeURI(props.match.params.category); - break; - case "/shows/details/:imdbId": - fetchShowDetails(props.match.params.imdbId); - fetchUrl = "" - } + <Route + {...otherProps} + render={props => { + let fetchUrl = ""; + switch (props.match.path) { + case "/shows/polochon": + fetchUrl = "/shows/polochon"; + break; + case "/shows/wishlist": + fetchUrl = "/wishlist/shows"; + break; + case "/shows/search/:search": + fetchUrl = "/shows/search/" + props.match.params.search; + break; + case "/shows/explore/:source/:category": + if (!isExplorerFetched) { + getShowExploreOptions(); + } + fetchUrl = + "/shows/explore?source=" + + encodeURI(props.match.params.source) + + "&category=" + + encodeURI(props.match.params.category); + break; + case "/shows/details/:imdbId": + fetchShowDetails(props.match.params.imdbId); + fetchUrl = ""; + } - if (fetchUrl != "") { - fetchShows(fetchUrl); - } + if (fetchUrl != "") { + fetchShows(fetchUrl); + } - return <Component {...props} /> - }} /> - ) -} + return <Component {...props} />; + }} + /> + ); +}; ShowsRoute.propTypes = { component: PropTypes.func, match: PropTypes.object, isExplorerFetched: PropTypes.bool.isRequired, fetchShows: PropTypes.func.isRequired, fetchShowDetails: PropTypes.func.isRequired, - getShowExploreOptions: PropTypes.func.isRequired, + getShowExploreOptions: PropTypes.func.isRequired }; export default connect(mapStateToProps, mapDispatchToProps)(ShowsRoute); diff --git a/frontend/js/components/torrents/list.js b/frontend/js/components/torrents/list.js index 3f931a0..43eb6ed 100644 --- a/frontend/js/components/torrents/list.js +++ b/frontend/js/components/torrents/list.js @@ -1,26 +1,29 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { Map, List } from "immutable" -import { connect } from "react-redux" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { Map, List } from "immutable"; +import { connect } from "react-redux"; -import { prettySize } from "../../utils" -import { fetchTorrents, addTorrent, removeTorrent } from "../../actions/torrents" +import { prettySize } from "../../utils"; +import { + fetchTorrents, + addTorrent, + removeTorrent +} from "../../actions/torrents"; -const mapStateToProps = (state) => ({ +const mapStateToProps = state => ({ torrents: state.torrentStore.get("torrents") }); const mapDispatchToProps = { - fetchTorrents, addTorrent, removeTorrent, + fetchTorrents, + addTorrent, + removeTorrent }; -const TorrentList = (props) => ( +const TorrentList = props => ( <div className="row"> <div className="col-12"> <AddTorrent addTorrent={props.addTorrent} /> - <Torrents - torrents={props.torrents} - removeTorrent={props.removeTorrent} - /> + <Torrents torrents={props.torrents} removeTorrent={props.removeTorrent} /> </div> </div> ); @@ -28,38 +31,40 @@ TorrentList.propTypes = { fetchTorrents: PropTypes.func.isRequired, addTorrent: PropTypes.func.isRequired, removeTorrent: PropTypes.func.isRequired, - torrents: PropTypes.instanceOf(List), + torrents: PropTypes.instanceOf(List) }; export default connect(mapStateToProps, mapDispatchToProps)(TorrentList); -const AddTorrent = (props) => { +const AddTorrent = props => { const [url, setUrl] = useState(""); - const handleSubmit = (e) => { + const handleSubmit = e => { e.preventDefault(); - if (url === "") { return; } + if (url === "") { + return; + } props.addTorrent(url); setUrl(""); - } + }; return ( - <form onSubmit={(e) => handleSubmit(e)}> + <form onSubmit={e => handleSubmit(e)}> <input type="text" className="form-control mb-3 w-100" placeholder="Add torrent URL" onSubmit={handleSubmit} value={url} - onChange={(e) => setUrl(e.target.value)} + onChange={e => setUrl(e.target.value)} /> </form> ); -} +}; AddTorrent.propTypes = { - addTorrent: PropTypes.func.isRequired, + addTorrent: PropTypes.func.isRequired }; -const Torrents = (props) => { +const Torrents = props => { if (props.torrents.size === 0) { return ( <div className="jumbotron"> @@ -71,31 +76,29 @@ const Torrents = (props) => { return ( <div className="d-flex flex-wrap"> {props.torrents.map((el, index) => ( - <Torrent - key={index} - data={el} - removeTorrent={props.removeTorrent} - /> + <Torrent key={index} data={el} removeTorrent={props.removeTorrent} /> ))} </div> ); -} +}; Torrents.propTypes = { removeTorrent: PropTypes.func.isRequired, - torrents: PropTypes.instanceOf(List), + torrents: PropTypes.instanceOf(List) }; -const Torrent = (props) => { +const Torrent = props => { const handleClick = () => { props.removeTorrent(props.data.get("id")); - } + }; const done = props.data.get("is_finished"); - var progressStyle = done ? "success" : "info progress-bar-striped progress-bar-animated"; + var progressStyle = done + ? "success" + : "info progress-bar-striped progress-bar-animated"; const progressBarClass = "progress-bar bg-" + progressStyle; var percentDone = props.data.get("percent_done"); - const started = (percentDone !== 0); + const started = percentDone !== 0; if (started) { percentDone = Number(percentDone).toFixed(1) + "%"; } @@ -108,32 +111,35 @@ const Torrent = (props) => { <div className="card w-100 mb-3"> <h5 className="card-header"> <span className="text text-break">{props.data.get("name")}</span> - <span className="fa fa-trash clickable pull-right" onClick={() => handleClick()}></span> + <span + className="fa fa-trash clickable pull-right" + onClick={() => handleClick()} + ></span> </h5> <div className="card-body pb-0"> - {started && - <React.Fragment> - <div className="progress bg-light"> - <div - className={progressBarClass} - style={{width: percentDone}} - role="progressbar" - aria-valuenow={percentDone} - aria-valuemin="0" - aria-valuemax="100" - ></div> - </div> - <p>{downloadedSize} / {totalSize} - {percentDone} - {downloadRate}</p> - </React.Fragment> - } - {!started && - <p>Download not yet started</p> - } + {started && ( + <React.Fragment> + <div className="progress bg-light"> + <div + className={progressBarClass} + style={{ width: percentDone }} + role="progressbar" + aria-valuenow={percentDone} + aria-valuemin="0" + aria-valuemax="100" + ></div> + </div> + <p> + {downloadedSize} / {totalSize} - {percentDone} - {downloadRate} + </p> + </React.Fragment> + )} + {!started && <p>Download not yet started</p>} </div> </div> ); -} +}; Torrent.propTypes = { removeTorrent: PropTypes.func.isRequired, - data: PropTypes.instanceOf(Map), + data: PropTypes.instanceOf(Map) }; diff --git a/frontend/js/components/torrents/search.js b/frontend/js/components/torrents/search.js index b40acb5..1bc1649 100644 --- a/frontend/js/components/torrents/search.js +++ b/frontend/js/components/torrents/search.js @@ -1,34 +1,37 @@ -import React, { useState, useEffect } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import { addTorrent, searchTorrents } from "../../actions/torrents" -import { Map, List } from "immutable" -import Loader from "../loader/loader" +import React, { useState, useEffect } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { addTorrent, searchTorrents } from "../../actions/torrents"; +import { Map, List } from "immutable"; +import Loader from "../loader/loader"; -import { OverlayTrigger, Tooltip } from "react-bootstrap" +import { OverlayTrigger, Tooltip } from "react-bootstrap"; -import { prettySize } from "../../utils" +import { prettySize } from "../../utils"; -const mapStateToProps = (state) => ({ - searching: state.torrentStore.get("searching"), - results: state.torrentStore.get("searchResults"), +const mapStateToProps = state => ({ + searching: state.torrentStore.get("searching"), + results: state.torrentStore.get("searchResults") }); const mapDispatchToProps = { addTorrent, searchTorrents }; -const TorrentSearch = (props) => { +const TorrentSearch = props => { const [search, setSearch] = useState(props.match.params.search || ""); const [type, setType] = useState(props.match.params.type || ""); const [url, setUrl] = useState(""); - const getUrl = () => - `/torrents/search/${type}/${encodeURI(search)}`; + const getUrl = () => `/torrents/search/${type}/${encodeURI(search)}`; useEffect(() => { - if (search === "") { return } - if (type === "") { return } + if (search === "") { + return; + } + if (type === "") { + return; + } const url = getUrl(); - props.searchTorrents(url) + props.searchTorrents(url); props.history.push(url); }, [url]); @@ -40,7 +43,7 @@ const TorrentSearch = (props) => { className="form-control mb-1 w-100 form-control-lg" placeholder="Search torrents" value={search} - onChange={(e) => setSearch(e.target.value)} + onChange={e => setSearch(e.target.value)} /> <div className="mb-3 w-100 d-flex"> <SearchButton @@ -50,7 +53,8 @@ const TorrentSearch = (props) => { handleClick={() => { setType("movies"); setUrl(getUrl()); - }}/> + }} + /> <SearchButton text="Search shows" type="shows" @@ -58,7 +62,8 @@ const TorrentSearch = (props) => { handleClick={() => { setType("shows"); setUrl(getUrl()); - }}/> + }} + /> </div> </div> <div className="col-12"> @@ -71,7 +76,7 @@ const TorrentSearch = (props) => { </div> </div> ); -} +}; TorrentSearch.propTypes = { searching: PropTypes.bool.isRequired, results: PropTypes.instanceOf(List), @@ -79,32 +84,31 @@ TorrentSearch.propTypes = { match: PropTypes.object, history: PropTypes.object, addTorrent: PropTypes.func.isRequired, - searchTorrents: PropTypes.func.isRequired, + searchTorrents: PropTypes.func.isRequired }; - -const SearchButton = (props) => { - const variant = (props.type === props.typeFromURL) ? "primary" : "secondary"; +const SearchButton = props => { + const variant = props.type === props.typeFromURL ? "primary" : "secondary"; return ( <button type="button" className={`w-50 btn m-1 btn-lg btn-${variant}`} onClick={props.handleClick} - > + > <i className="fa fa-search" aria-hidden="true"></i> {props.text} </button> ); -} +}; SearchButton.propTypes = { type: PropTypes.string, typeFromURL: PropTypes.string, text: PropTypes.string, - handleClick: PropTypes.func.isRequired, + handleClick: PropTypes.func.isRequired }; -const TorrentList = (props) => { +const TorrentList = props => { if (props.searching) { - return (<Loader />); + return <Loader />; } if (props.searchFromURL === "") { @@ -122,59 +126,65 @@ const TorrentList = (props) => { return ( <React.Fragment> {props.results.map(function(el, index) { - return ( - <Torrent - key={index} - data={el} - addTorrent={props.addTorrent} - />); + return <Torrent key={index} data={el} addTorrent={props.addTorrent} />; })} </React.Fragment> ); -} +}; TorrentList.propTypes = { searching: PropTypes.bool.isRequired, results: PropTypes.instanceOf(List), searchFromURL: PropTypes.string, - addTorrent: PropTypes.func.isRequired, + addTorrent: PropTypes.func.isRequired }; -const Torrent = (props) => ( +const Torrent = props => ( <div className="alert d-flex border-bottom border-secondary align-items-center"> <TorrentHealth url={props.data.get("url")} seeders={props.data.get("seeders")} leechers={props.data.get("leechers")} /> - <span className="mx-3 text text-start text-break flex-fill">{props.data.get("name")}</span> + <span className="mx-3 text text-start text-break flex-fill"> + {props.data.get("name")} + </span> <div> - {props.data.get("size") !== 0 && - <span className="mx-1 badge badge-pill badge-warning"> - {prettySize(props.data.get("size"))} - </span> - } + {props.data.get("size") !== 0 && ( + <span className="mx-1 badge badge-pill badge-warning"> + {prettySize(props.data.get("size"))} + </span> + )} - <span className="mx-1 badge badge-pill badge-warning">{props.data.get("quality")}</span> - <span className="mx-1 badge badge-pill badge-success">{props.data.get("source")}</span> - <span className="mx-1 badge badge-pill badge-info">{props.data.get("upload_user")}</span> + <span className="mx-1 badge badge-pill badge-warning"> + {props.data.get("quality")} + </span> + <span className="mx-1 badge badge-pill badge-success"> + {props.data.get("source")} + </span> + <span className="mx-1 badge badge-pill badge-info"> + {props.data.get("upload_user")} + </span> </div> <div className="align-self-end ml-3"> - <i className="fa fa-cloud-download clickable" onClick={() => props.addTorrent(props.data.get("url"))}></i> + <i + className="fa fa-cloud-download clickable" + onClick={() => props.addTorrent(props.data.get("url"))} + ></i> </div> </div> ); Torrent.propTypes = { data: PropTypes.instanceOf(Map), - addTorrent: PropTypes.func.isRequired, + addTorrent: PropTypes.func.isRequired }; -const TorrentHealth = (props) => { +const TorrentHealth = props => { const seeders = props.seeders || 0; const leechers = props.leechers || 1; let color; let health; - let ratio = seeders/leechers; + let ratio = seeders / leechers; if (seeders > 20) { health = "good"; @@ -192,7 +202,9 @@ const TorrentHealth = (props) => { const className = `align-self-start text text-center text-${color}`; const tooltip = ( <Tooltip id={`tooltip-health-${props.url}`}> - <p><span className={className}>Health: {health}</span></p> + <p> + <span className={className}>Health: {health}</span> + </p> <p>Seeders: {seeders}</p> <p>Leechers: {props.leechers}</p> </Tooltip> @@ -205,11 +217,11 @@ const TorrentHealth = (props) => { </span> </OverlayTrigger> ); -} +}; TorrentHealth.propTypes = { url: PropTypes.string, seeders: PropTypes.number, - leechers: PropTypes.number, + leechers: PropTypes.number }; export default connect(mapStateToProps, mapDispatchToProps)(TorrentSearch); diff --git a/frontend/js/components/users/activation.js b/frontend/js/components/users/activation.js index 5de1cda..2113b43 100644 --- a/frontend/js/components/users/activation.js +++ b/frontend/js/components/users/activation.js @@ -1,20 +1,20 @@ -import React from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import { Redirect, Link } from "react-router-dom" +import React from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { Redirect, Link } from "react-router-dom"; -const mapStateToProps = (state) => ({ - isActivated: state.userStore.get("isActivated"), - isLogged: state.userStore.get("isLogged"), +const mapStateToProps = state => ({ + isActivated: state.userStore.get("isActivated"), + isLogged: state.userStore.get("isLogged") }); -const UserActivation = (props) => { +const UserActivation = props => { if (!props.isLogged) { - return (<Redirect to="/users/login"/>); + return <Redirect to="/users/login" />; } if (props.isActivated) { - return (<Redirect to="/"/>); + return <Redirect to="/" />; } return ( @@ -22,15 +22,18 @@ const UserActivation = (props) => { <div className="col-12 col-md-8 offset-md-2"> <h2>Waiting for activation</h2> <hr /> - <h3>Hang tight! Your user will soon be activated by the administrators of this site.</h3> + <h3> + Hang tight! Your user will soon be activated by the administrators of + this site. + </h3> <Link to="/users/logout">Logout</Link> </div> </div> ); -} +}; UserActivation.propTypes = { isActivated: PropTypes.bool.isRequired, - isLogged: PropTypes.bool.isRequired, + isLogged: PropTypes.bool.isRequired }; export default connect(mapStateToProps)(UserActivation); diff --git a/frontend/js/components/users/edit.js b/frontend/js/components/users/edit.js index adecb62..e54e08a 100644 --- a/frontend/js/components/users/edit.js +++ b/frontend/js/components/users/edit.js @@ -1,24 +1,26 @@ -import React, { useState, useEffect } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import Loader from "../loader/loader" -import { List } from "immutable" +import React, { useState, useEffect } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import Loader from "../loader/loader"; +import { List } from "immutable"; -import { getUserInfos, updateUser } from "../../actions/users" -import { getPolochons } from "../../actions/polochon" +import { getUserInfos, updateUser } from "../../actions/users"; +import { getPolochons } from "../../actions/polochon"; -import { PolochonSelect } from "../polochons/select" +import { PolochonSelect } from "../polochons/select"; -const mapStateToProps = (state) => ({ +const mapStateToProps = state => ({ loading: state.userStore.get("loading"), publicPolochons: state.polochon.get("public"), polochonId: state.userStore.get("polochonId"), - polochonActivated: state.userStore.get("polochonActivated"), + polochonActivated: state.userStore.get("polochonActivated") }); const mapDispatchToProps = { - updateUser, getPolochons, getUserInfos, -} + updateUser, + getPolochons, + getUserInfos +}; const UserEditConnect = ({ loading, @@ -27,7 +29,7 @@ const UserEditConnect = ({ updateUser, getPolochons, getUserInfos, - publicPolochons, + publicPolochons }) => { const [id, setId] = useState(polochonId); const [password, setPassword] = useState(""); @@ -36,37 +38,45 @@ const UserEditConnect = ({ useEffect(() => { getPolochons(); getUserInfos(); - }, [getPolochons, getUserInfos]) + }, [getPolochons, getUserInfos]); useEffect(() => { setId(polochonId); - }, [polochonId]) + }, [polochonId]); - const handleSubmit = (ev) => { + const handleSubmit = ev => { ev.preventDefault(); updateUser({ - "password": password, - "password_confirm": passwordConfirm, - "polochon_id": id, + password: password, + password_confirm: passwordConfirm, + polochon_id: id }); - } + }; - if (loading) { return (<Loader />) } + if (loading) { + return <Loader />; + } return ( <div className="row mb-3"> <div className="col-12 col-md-8 offset-md-2"> <h2>Edit user</h2> <hr /> - <form className="form-horizontal" onSubmit={(ev) => handleSubmit(ev)}> + <form className="form-horizontal" onSubmit={ev => handleSubmit(ev)}> <div className="form-group"> <label className="control-label"> Polochon - {polochonActivated || - <span className="ml-1 text text-primary">(Needs activation from admin)</span> - } + {polochonActivated || ( + <span className="ml-1 text text-primary"> + (Needs activation from admin) + </span> + )} </label> - <PolochonSelect value={id} changeValue={setId} polochonList={publicPolochons} /> + <PolochonSelect + value={id} + changeValue={setId} + polochonList={publicPolochons} + /> </div> <hr /> @@ -78,7 +88,7 @@ const UserEditConnect = ({ type="password" autoComplete="off" value={password} - onChange={(e) => setPassword(e.target.value)} + onChange={e => setPassword(e.target.value)} /> </div> @@ -89,18 +99,22 @@ const UserEditConnect = ({ type="password" autoComplete="off" value={passwordConfirm} - onChange={(e) => setPasswordConfirm(e.target.value)} + onChange={e => setPasswordConfirm(e.target.value)} /> </div> <div> - <input type="submit" className="btn btn-primary pull-right" value="Update"/> + <input + type="submit" + className="btn btn-primary pull-right" + value="Update" + /> </div> </form> </div> </div> ); -} +}; UserEditConnect.propTypes = { loading: PropTypes.bool.isRequired, polochonId: PropTypes.string, @@ -108,7 +122,10 @@ UserEditConnect.propTypes = { updateUser: PropTypes.func, getPolochons: PropTypes.func, getUserInfos: PropTypes.func, - publicPolochons: PropTypes.instanceOf(List), + publicPolochons: PropTypes.instanceOf(List) }; -export const UserEdit = connect(mapStateToProps, mapDispatchToProps)(UserEditConnect); +export const UserEdit = connect( + mapStateToProps, + mapDispatchToProps +)(UserEditConnect); diff --git a/frontend/js/components/users/login.js b/frontend/js/components/users/login.js index e7cc303..76f8c97 100644 --- a/frontend/js/components/users/login.js +++ b/frontend/js/components/users/login.js @@ -1,27 +1,27 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import { Redirect, Link } from "react-router-dom" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { Redirect, Link } from "react-router-dom"; -import { loginUser } from "../../actions/users" +import { loginUser } from "../../actions/users"; -const mapStateToProps = (state) => ({ +const mapStateToProps = state => ({ isLogged: state.userStore.get("isLogged"), isLoading: state.userStore.get("loading"), - error: state.userStore.get("error"), + error: state.userStore.get("error") }); const mapDispatchToProps = { loginUser }; -const UserLoginForm = (props) => { +const UserLoginForm = props => { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); - const handleSubmit = (e) => { + const handleSubmit = e => { e.preventDefault(); if (!props.isLoading) { props.loginUser(username, password); } - } + }; if (props.isLogged) { return <Redirect to="/" />; @@ -31,25 +31,33 @@ const UserLoginForm = (props) => { <div className="row"> <div className="col-10 offset-1 col-md-6 offset-md-3"> <h2>Log in</h2> - <hr/> - {props.error && props.error !== "" && - <div className="alert alert-danger"> - {props.error} - </div> - } - <form className="form-horizontal" onSubmit={(e) => handleSubmit(e)}> + <hr /> + {props.error && props.error !== "" && ( + <div className="alert alert-danger">{props.error}</div> + )} + <form className="form-horizontal" onSubmit={e => handleSubmit(e)}> <div> <label>Username</label> - <br/> - <input className="form-control" type="username" autoFocus - value={username} onChange={(e) => setUsername(e.target.value)}/> + <br /> + <input + className="form-control" + type="username" + autoFocus + value={username} + onChange={e => setUsername(e.target.value)} + /> <p></p> </div> <div> <label>Password</label> - <br/> - <input className="form-control" type="password" autoComplete="new-password" - value={password} onChange={(e) => setPassword(e.target.value)}/> + <br /> + <input + className="form-control" + type="password" + autoComplete="new-password" + value={password} + onChange={e => setPassword(e.target.value)} + /> <p></p> </div> <div> @@ -58,28 +66,32 @@ const UserLoginForm = (props) => { No account yet ? <Link to="/users/signup">Create one</Link> </small> </span> - {props.isLoading && - <button className="btn btn-primary pull-right"> - <i className="fa fa-spinner fa-spin"></i> - </button> - } - {props.isLoading || - <span className="spaced-icons"> - <input className="btn btn-primary pull-right" type="submit" value="Log in"/> - </span> - } - <br/> + {props.isLoading && ( + <button className="btn btn-primary pull-right"> + <i className="fa fa-spinner fa-spin"></i> + </button> + )} + {props.isLoading || ( + <span className="spaced-icons"> + <input + className="btn btn-primary pull-right" + type="submit" + value="Log in" + /> + </span> + )} + <br /> </div> </form> </div> </div> ); -} +}; UserLoginForm.propTypes = { loginUser: PropTypes.func.isRequired, isLoading: PropTypes.bool.isRequired, isLogged: PropTypes.bool.isRequired, - error: PropTypes.string, + error: PropTypes.string }; export default connect(mapStateToProps, mapDispatchToProps)(UserLoginForm); diff --git a/frontend/js/components/users/logout.js b/frontend/js/components/users/logout.js index 34e2c9b..fb616ef 100644 --- a/frontend/js/components/users/logout.js +++ b/frontend/js/components/users/logout.js @@ -1,28 +1,26 @@ -import React from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import { Redirect } from "react-router-dom" +import React from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { Redirect } from "react-router-dom"; -import { userLogout } from "../../actions/users" +import { userLogout } from "../../actions/users"; -const mapStateToProps = (state) => ({ - isLogged: state.userStore.get("isLogged"), +const mapStateToProps = state => ({ + isLogged: state.userStore.get("isLogged") }); const mapDispatchToProps = { userLogout }; -const UserLogout = (props) => { +const UserLogout = props => { if (props.isLogged) { props.userLogout(); } - return ( - <Redirect to="/users/login" /> - ); -} + return <Redirect to="/users/login" />; +}; UserLogout.propTypes = { isLogged: PropTypes.bool.isRequired, userLogout: PropTypes.func.isRequired, - history: PropTypes.object, + history: PropTypes.object }; export default connect(mapStateToProps, mapDispatchToProps)(UserLogout); diff --git a/frontend/js/components/users/profile.js b/frontend/js/components/users/profile.js index 031b73e..fb2c1bf 100644 --- a/frontend/js/components/users/profile.js +++ b/frontend/js/components/users/profile.js @@ -1,46 +1,38 @@ -import React, { useEffect } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import { Map } from "immutable" +import React, { useEffect } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { Map } from "immutable"; -import { PolochonList } from "../polochons/list" -import { UserEdit } from "./edit" +import { PolochonList } from "../polochons/list"; +import { UserEdit } from "./edit"; -import { getUserModules } from "../../actions/users" -import Modules from "../modules/modules" +import { getUserModules } from "../../actions/users"; +import Modules from "../modules/modules"; -const mapStateToProps = (state) => ({ - modules : state.userStore.get("modules"), - modulesLoading : state.userStore.get("modulesLoading"), +const mapStateToProps = state => ({ + modules: state.userStore.get("modules"), + modulesLoading: state.userStore.get("modulesLoading") }); -const mapDispatchToProps = { getUserModules } +const mapDispatchToProps = { getUserModules }; -const UserProfile = ({ - modules, - modulesLoading, - getUserModules - -}) => { +const UserProfile = ({ modules, modulesLoading, getUserModules }) => { useEffect(() => { getUserModules(); - }, [getUserModules]) + }, [getUserModules]); return ( <div> <UserEdit /> <PolochonList /> - <Modules - modules={modules} - isLoading={modulesLoading} - /> + <Modules modules={modules} isLoading={modulesLoading} /> </div> - ) -} + ); +}; UserProfile.propTypes = { getUserModules: PropTypes.func.isRequired, modules: PropTypes.instanceOf(Map), - modulesLoading: PropTypes.bool.isRequired, + modulesLoading: PropTypes.bool.isRequired }; export default connect(mapStateToProps, mapDispatchToProps)(UserProfile); diff --git a/frontend/js/components/users/signup.js b/frontend/js/components/users/signup.js index 0118bf0..748b580 100644 --- a/frontend/js/components/users/signup.js +++ b/frontend/js/components/users/signup.js @@ -1,86 +1,100 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import { Redirect } from "react-router-dom" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { Redirect } from "react-router-dom"; -import { userSignUp } from "../../actions/users" +import { userSignUp } from "../../actions/users"; -const mapStateToProps = (state) => ({ +const mapStateToProps = state => ({ isLogged: state.userStore.get("isLogged"), isLoading: state.userStore.get("loading"), - error: state.userStore.get("error"), + error: state.userStore.get("error") }); const mapDispatchToProps = { userSignUp }; -const UserSignUp = (props) => { +const UserSignUp = props => { if (props.isLogged) { - return (<Redirect to="/"/>); + return <Redirect to="/" />; } const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const [passwordConfirm, setPasswordConfirm] = useState(""); - const handleSubmit = (e) => { + const handleSubmit = e => { e.preventDefault(); props.userSignUp({ - "username": username, - "password": password, - "password_confirm": passwordConfirm, + username: username, + password: password, + password_confirm: passwordConfirm }); - } + }; return ( <div className="Row"> <div className="col-10 offset-1 col-md-6 offset-md-3"> <h2>Sign up</h2> <hr /> - {props.error && props.error !== "" && - <div className="alert alert-danger"> - {props.error} - </div> - } + {props.error && props.error !== "" && ( + <div className="alert alert-danger">{props.error}</div> + )} - <form className="form-horizontal" onSubmit={(e) => handleSubmit(e)}> + <form className="form-horizontal" onSubmit={e => handleSubmit(e)}> <div className="form-group"> <label className="control-label">Username</label> - <input autoFocus="autofocus" className="form-control" - value={username} onChange={(e) => setUsername(e.target.value)} /> + <input + autoFocus="autofocus" + className="form-control" + value={username} + onChange={e => setUsername(e.target.value)} + /> </div> <div className="form-group"> <label className="control-label">Password</label> - <input className="form-control" type="password" - value={password} onChange={(e) => setPassword(e.target.value)} /> + <input + className="form-control" + type="password" + value={password} + onChange={e => setPassword(e.target.value)} + /> </div> <div className="form-group"> <label className="control-label">Password confirm</label> - <input className="form-control" type="password" - value={passwordConfirm} onChange={(e) => setPasswordConfirm(e.target.value)} /> + <input + className="form-control" + type="password" + value={passwordConfirm} + onChange={e => setPasswordConfirm(e.target.value)} + /> </div> <div> - {props.isLoading && - <button className="btn btn-primary pull-right"> - <i className="fa fa-spinner fa-spin"></i> - </button> - } - {props.isLoading || - <span> - <input className="btn btn-primary pull-right" type="submit" value="Sign up"/> - </span> - } + {props.isLoading && ( + <button className="btn btn-primary pull-right"> + <i className="fa fa-spinner fa-spin"></i> + </button> + )} + {props.isLoading || ( + <span> + <input + className="btn btn-primary pull-right" + type="submit" + value="Sign up" + /> + </span> + )} </div> </form> </div> </div> ); -} +}; UserSignUp.propTypes = { isLogged: PropTypes.bool.isRequired, isLoading: PropTypes.bool.isRequired, userSignUp: PropTypes.func.isRequired, - error: PropTypes.string, + error: PropTypes.string }; export default connect(mapStateToProps, mapDispatchToProps)(UserSignUp); diff --git a/frontend/js/components/users/tokens.js b/frontend/js/components/users/tokens.js index b135078..f1a1257 100644 --- a/frontend/js/components/users/tokens.js +++ b/frontend/js/components/users/tokens.js @@ -1,18 +1,18 @@ -import React, { useState } from "react" -import PropTypes from "prop-types" -import { connect } from "react-redux" -import { UAParser } from "ua-parser-js" -import moment from "moment" -import { Map, List } from "immutable" +import React, { useState } from "react"; +import PropTypes from "prop-types"; +import { connect } from "react-redux"; +import { UAParser } from "ua-parser-js"; +import moment from "moment"; +import { Map, List } from "immutable"; -import { getUserTokens, deleteUserToken } from "../../actions/users" +import { getUserTokens, deleteUserToken } from "../../actions/users"; -const mapStateToProps = (state) => ({ - tokens: state.userStore.get("tokens"), +const mapStateToProps = state => ({ + tokens: state.userStore.get("tokens") }); const mapDispatchToProps = { getUserTokens, deleteUserToken }; -const UserTokens = (props) => { +const UserTokens = props => { const [fetched, setIsFetched] = useState(false); if (!fetched) { props.getUserTokens(); @@ -28,15 +28,15 @@ const UserTokens = (props) => { </div> </div> ); -} +}; UserTokens.propTypes = { tokens: PropTypes.instanceOf(List), isLoading: PropTypes.bool.isRequired, getUserTokens: PropTypes.func.isRequired, - deleteUserToken: PropTypes.func.isRequired, + deleteUserToken: PropTypes.func.isRequired }; -const Token = (props) => { +const Token = props => { const ua = UAParser(props.data.get("user_agent")); return ( <div className="card mt-3"> @@ -54,40 +54,46 @@ const Token = (props) => { <p>Created: {moment(props.data.get("created_at")).fromNow()}</p> </div> <div className="col-12 col-md-6"> - <p>Device: <Device {...ua.device}/></p> - <p>OS: <OS {...ua.os}/></p> - <p>Browser: <Browser {...ua.browser}/></p> + <p> + Device: <Device {...ua.device} /> + </p> + <p> + OS: <OS {...ua.os} /> + </p> + <p> + Browser: <Browser {...ua.browser} /> + </p> </div> </div> </div> ); -} +}; Token.propTypes = { - data: PropTypes.instanceOf(Map).isRequired, + data: PropTypes.instanceOf(Map).isRequired }; -const Actions = (props) => { +const Actions = props => { const handleClick = () => { props.deleteToken(props.data.get("token")); - } + }; return ( <span className="fa fa-trash fa-lg pull-right clickable" - onClick={handleClick}> - </span> + onClick={handleClick} + ></span> ); -} +}; Actions.propTypes = { data: PropTypes.instanceOf(Map).isRequired, - deleteToken: PropTypes.func.isRequired, + deleteToken: PropTypes.func.isRequired }; -const Logo = (props) => { +const Logo = props => { var className; if (props.ua === "canape-cli") { className = "terminal"; - } else if (props.device.type == "mobile" ){ + } else if (props.device.type == "mobile") { className = "mobile"; } else { switch (props.browser.name) { @@ -109,10 +115,10 @@ const Logo = (props) => { } } - return (<span className={`fa fa-${className}`}></span>); -} + return <span className={`fa fa-${className}`}></span>; +}; -const OS = (props) => { +const OS = props => { var osName = "-"; if (props.name !== undefined) { @@ -123,24 +129,20 @@ const OS = (props) => { } } - return ( - <span> {osName}</span> - ); -} + return <span> {osName}</span>; +}; -const Device = (props) => { +const Device = props => { var deviceName = "-"; if (props.model !== undefined) { deviceName = props.model; } - return ( - <span> {deviceName}</span> - ); -} + return <span> {deviceName}</span>; +}; -const Browser = (props) => { +const Browser = props => { var browserName = "-"; if (props.name !== undefined) { browserName = props.name; @@ -150,9 +152,7 @@ const Browser = (props) => { } } - return ( - <span> {browserName}</span> - ); -} + return <span> {browserName}</span>; +}; export default connect(mapStateToProps, mapDispatchToProps)(UserTokens); diff --git a/frontend/js/components/websocket.js b/frontend/js/components/websocket.js index 49ff8ae..a54fbf9 100644 --- a/frontend/js/components/websocket.js +++ b/frontend/js/components/websocket.js @@ -1,22 +1,26 @@ -import { useEffect, useState } from "react" -import { connect } from "react-redux" -import { setFetchedTorrents } from "../actions/torrents" -import { newMovieEvent } from "../actions/movies" -import { newEpisodeEvent } from "../actions/shows" +import { useEffect, useState } from "react"; +import { connect } from "react-redux"; +import { setFetchedTorrents } from "../actions/torrents"; +import { newMovieEvent } from "../actions/movies"; +import { newEpisodeEvent } from "../actions/shows"; -const mapStateToProps = (state) => ({ - isLogged: state.userStore.get("isLogged"), +const mapStateToProps = state => ({ + isLogged: state.userStore.get("isLogged") }); -const mapDispatchToProps = { setFetchedTorrents, newMovieEvent, newEpisodeEvent }; +const mapDispatchToProps = { + setFetchedTorrents, + newMovieEvent, + newEpisodeEvent +}; -const WsHandler = (props) => { +const WsHandler = props => { const [ws, setWs] = useState(null); useEffect(() => { const intervalID = setInterval(() => { if (!ws) { connect(); - return + return; } if (ws.readyState === WebSocket.CLOSED) { @@ -38,41 +42,51 @@ const WsHandler = (props) => { const stop = () => { if (!ws) { - return + return; } - ws.close() + ws.close(); setWs(null); - } + }; const connect = () => { - if (ws) { return; } + if (ws) { + return; + } if (!props.isLogged) { stop(); } - const type = (location.protocol === "https:") ? "wss" : "ws"; - const socket = new WebSocket(type + ":" + location.host + "/events") + const type = location.protocol === "https:" ? "wss" : "ws"; + const socket = new WebSocket(type + ":" + location.host + "/events"); socket.onopen = () => { - socket.send(JSON.stringify({ - "type": "subscribe", - "message": "torrents", - })) - socket.send(JSON.stringify({ - "type": "subscribe", - "message": "newVideo", - })) - } + socket.send( + JSON.stringify({ + type: "subscribe", + message: "torrents" + }) + ); + socket.send( + JSON.stringify({ + type: "subscribe", + message: "newVideo" + }) + ); + }; - socket.onmessage = (event) => { - if (!event.data) { return } + socket.onmessage = event => { + if (!event.data) { + return; + } const data = JSON.parse(event.data); - if (!data.type){ return } + if (!data.type) { + return; + } if (data.status !== "ok") { // TODO: handle this somehow - return + return; } switch (data.type) { @@ -81,20 +95,22 @@ const WsHandler = (props) => { break; case "newVideo": if (data.message.type === "movie") { - props.newMovieEvent(data.message.data) + props.newMovieEvent(data.message.data); } else if (data.message.type === "episode") { - props.newEpisodeEvent(data.message.data) + props.newEpisodeEvent(data.message.data); } break; } - } + }; - socket.onerror = () => { stop(); } + socket.onerror = () => { + stop(); + }; - setWs(socket) - } + setWs(socket); + }; return null; -} +}; export default connect(mapStateToProps, mapDispatchToProps)(WsHandler); diff --git a/frontend/js/reducers/admins.js b/frontend/js/reducers/admins.js index 35c4e92..6887bda 100644 --- a/frontend/js/reducers/admins.js +++ b/frontend/js/reducers/admins.js @@ -1,21 +1,26 @@ -import { Map, List, fromJS } from "immutable" +import { Map, List, fromJS } from "immutable"; export const defaultState = Map({ - "fetchingModules": false, - "users": List(), - "stats": Map({}), - "modules": Map({}), + fetchingModules: false, + users: List(), + stats: Map({}), + modules: Map({}) }); const handlers = { - "ADMIN_LIST_USERS_FULFILLED": (state, action) => state.set("users", fromJS(action.payload.response.data)), - "ADMIN_GET_STATS_FULFILLED": (state, action) => state.set("stats", fromJS(action.payload.response.data)), - "ADMIN_GET_MODULES_PENDING": state => state.set("fetchingModules", true), - "ADMIN_GET_MODULES_FULFILLED": (state, action) => state.merge(fromJS({ - "modules": action.payload.response.data, - "fetchingModules": false, - })), -} + ADMIN_LIST_USERS_FULFILLED: (state, action) => + state.set("users", fromJS(action.payload.response.data)), + ADMIN_GET_STATS_FULFILLED: (state, action) => + state.set("stats", fromJS(action.payload.response.data)), + ADMIN_GET_MODULES_PENDING: state => state.set("fetchingModules", true), + ADMIN_GET_MODULES_FULFILLED: (state, action) => + state.merge( + fromJS({ + modules: action.payload.response.data, + fetchingModules: false + }) + ) +}; export default (state = defaultState, action) => handlers[action.type] ? handlers[action.type](state, action) : state; diff --git a/frontend/js/reducers/alerts.js b/frontend/js/reducers/alerts.js index e51855d..33bf094 100644 --- a/frontend/js/reducers/alerts.js +++ b/frontend/js/reducers/alerts.js @@ -1,29 +1,37 @@ -import { Map } from "immutable" +import { Map } from "immutable"; const defaultState = Map({ show: false, message: "", - type: "", + type: "" }); - const handlers = { - "ADD_ALERT_ERROR": (state, action) => state.merge(Map({ - message: action.payload.message, - show: true, - type: "error", - })), - "ADD_ALERT_OK": (state, action) => state.merge(Map({ + ADD_ALERT_ERROR: (state, action) => + state.merge( + Map({ message: action.payload.message, show: true, - type: "success", - })), - "DISMISS_ALERT": state => state.merge(Map({ + type: "error" + }) + ), + ADD_ALERT_OK: (state, action) => + state.merge( + Map({ + message: action.payload.message, + show: true, + type: "success" + }) + ), + DISMISS_ALERT: state => + state.merge( + Map({ message: "", show: false, - type: "", - })), -} + type: "" + }) + ) +}; export default (state = defaultState, action) => handlers[action.type] ? handlers[action.type](state, action) : state; diff --git a/frontend/js/reducers/index.js b/frontend/js/reducers/index.js index 884b3c5..679de67 100644 --- a/frontend/js/reducers/index.js +++ b/frontend/js/reducers/index.js @@ -1,14 +1,14 @@ import { combineReducers } from "redux"; -import movieStore from "./movies" -import showsStore from "./shows" -import showStore from "./show" -import userStore from "./users" -import alerts from "./alerts" -import torrentStore from "./torrents" -import adminStore from "./admins" -import polochon from "./polochon" -import notifications from "./notifications" +import movieStore from "./movies"; +import showsStore from "./shows"; +import showStore from "./show"; +import userStore from "./users"; +import alerts from "./alerts"; +import torrentStore from "./torrents"; +import adminStore from "./admins"; +import polochon from "./polochon"; +import notifications from "./notifications"; export default combineReducers({ movieStore, @@ -19,5 +19,5 @@ export default combineReducers({ torrentStore, adminStore, polochon, - notifications, + notifications }); diff --git a/frontend/js/reducers/movies.js b/frontend/js/reducers/movies.js index 8c48427..dad75f4 100644 --- a/frontend/js/reducers/movies.js +++ b/frontend/js/reducers/movies.js @@ -1,4 +1,4 @@ -import { OrderedMap, Map, fromJS } from "immutable" +import { OrderedMap, Map, fromJS } from "immutable"; const defaultState = Map({ loading: false, @@ -6,61 +6,95 @@ const defaultState = Map({ filter: "", selectedImdbId: "", lastFetchUrl: "", - exploreOptions: Map(), + exploreOptions: Map() }); const handlers = { - "MOVIE_LIST_FETCH_PENDING": state => state.set("loading", true), - "MOVIE_LIST_FETCH_ERROR": state => state.set("loading", false), - "MOVIE_LIST_FETCH_FULFILLED": (state, action) => { - let allMoviesInPolochon = true - let movies = Map() - action.payload.response.data.map(function (movie) { + MOVIE_LIST_FETCH_PENDING: state => state.set("loading", true), + MOVIE_LIST_FETCH_ERROR: state => state.set("loading", false), + MOVIE_LIST_FETCH_FULFILLED: (state, action) => { + let allMoviesInPolochon = true; + let movies = Map(); + action.payload.response.data.map(function(movie) { movie.fetchingDetails = false; movie.fetchingSubtitles = false; if (movie.polochon_url === "") { - allMoviesInPolochon = false + allMoviesInPolochon = false; } movies = movies.set(movie.imdb_id, fromJS(movie)); - }) + }); // Select the first movie if the list is not empty let selectedImdbId = ""; if (movies.size > 0) { // Sort by year - movies = movies.sort((a,b) => { + movies = movies.sort((a, b) => { if (!allMoviesInPolochon) { - return b.get("year") - a.get("year") + return b.get("year") - a.get("year"); } - const dateA = new Date(a.get("date_added")) - const dateB = new Date(b.get("date_added")) + const dateA = new Date(a.get("date_added")); + const dateB = new Date(b.get("date_added")); return dateA > dateB ? -1 : dateA < dateB ? 1 : 0; }); selectedImdbId = movies.first().get("imdb_id"); } - return state.delete("movies").merge(Map({ - movies: movies, - filter: "", - loading: false, - selectedImdbId: selectedImdbId, - })) + return state.delete("movies").merge( + Map({ + movies: movies, + filter: "", + loading: false, + selectedImdbId: selectedImdbId + }) + ); }, - "MOVIE_GET_DETAILS_PENDING" : (state, action) => state.setIn(["movies", action.payload.main.imdbId, "fetchingDetails"], true), - "MOVIE_GET_DETAILS_FULFILLED" : (state, action) => state.setIn(["movies", action.payload.response.data.imdb_id], fromJS(action.payload.response.data)) - .setIn(["movies", action.payload.response.data.imdb_id, "fetchingDetails"], false) - .setIn(["movies", action.payload.response.data.imdb_id, "fetchingSubtitles"], false), - "MOVIE_UPDATE_STORE_WISHLIST" : (state, action) => state.setIn(["movies", action.payload.imdbId, "wishlisted"], action.payload.wishlisted), - "MOVIE_GET_EXPLORE_OPTIONS_FULFILLED" : (state, action) => state.set("exploreOptions", fromJS(action.payload.response.data)), - "UPDATE_LAST_MOVIE_FETCH_URL" : (state, action) => state.set("lastFetchUrl", action.payload.url), - "MOVIE_SUBTITLES_UPDATE_PENDING" : (state, action) => state.setIn(["movies", action.payload.main.imdbId, "fetchingSubtitles"], true), - "MOVIE_SUBTITLES_UPDATE_FULFILLED" : (state, action) => state.setIn(["movies", action.payload.main.imdbId, "fetchingSubtitles"], false) - .setIn(["movies", action.payload.main.imdbId, "subtitles"], fromJS(action.payload.response.data)), - "SELECT_MOVIE" : (state, action) => state.set("selectedImdbId", action.payload.imdbId), - "MOVIE_UPDATE_FILTER" : (state, action) => state.set("filter", action.payload.filter), -} + MOVIE_GET_DETAILS_PENDING: (state, action) => + state.setIn( + ["movies", action.payload.main.imdbId, "fetchingDetails"], + true + ), + MOVIE_GET_DETAILS_FULFILLED: (state, action) => + state + .setIn( + ["movies", action.payload.response.data.imdb_id], + fromJS(action.payload.response.data) + ) + .setIn( + ["movies", action.payload.response.data.imdb_id, "fetchingDetails"], + false + ) + .setIn( + ["movies", action.payload.response.data.imdb_id, "fetchingSubtitles"], + false + ), + MOVIE_UPDATE_STORE_WISHLIST: (state, action) => + state.setIn( + ["movies", action.payload.imdbId, "wishlisted"], + action.payload.wishlisted + ), + MOVIE_GET_EXPLORE_OPTIONS_FULFILLED: (state, action) => + state.set("exploreOptions", fromJS(action.payload.response.data)), + UPDATE_LAST_MOVIE_FETCH_URL: (state, action) => + state.set("lastFetchUrl", action.payload.url), + MOVIE_SUBTITLES_UPDATE_PENDING: (state, action) => + state.setIn( + ["movies", action.payload.main.imdbId, "fetchingSubtitles"], + true + ), + MOVIE_SUBTITLES_UPDATE_FULFILLED: (state, action) => + state + .setIn(["movies", action.payload.main.imdbId, "fetchingSubtitles"], false) + .setIn( + ["movies", action.payload.main.imdbId, "subtitles"], + fromJS(action.payload.response.data) + ), + SELECT_MOVIE: (state, action) => + state.set("selectedImdbId", action.payload.imdbId), + MOVIE_UPDATE_FILTER: (state, action) => + state.set("filter", action.payload.filter) +}; export default (state = defaultState, action) => handlers[action.type] ? handlers[action.type](state, action) : state; diff --git a/frontend/js/reducers/notifications.js b/frontend/js/reducers/notifications.js index 64c0332..a71c36f 100644 --- a/frontend/js/reducers/notifications.js +++ b/frontend/js/reducers/notifications.js @@ -1,15 +1,20 @@ -import { List, fromJS } from "immutable" +import { List, fromJS } from "immutable"; const defaultState = List(); const handlers = { - "ADD_NOTIFICATION": (state, action) => state.push(fromJS({ - id: Math.random().toString(36).substring(7), - ...action.payload - })), - "REMOVE_NOTIFICATION": (state, action) => - state.filter((e) => (e.get("id") !== action.payload.id)), -} + ADD_NOTIFICATION: (state, action) => + state.push( + fromJS({ + id: Math.random() + .toString(36) + .substring(7), + ...action.payload + }) + ), + REMOVE_NOTIFICATION: (state, action) => + state.filter(e => e.get("id") !== action.payload.id) +}; export default (state = defaultState, action) => handlers[action.type] ? handlers[action.type](state, action) : state; diff --git a/frontend/js/reducers/polochon.js b/frontend/js/reducers/polochon.js index c7c4dc0..b0057d1 100644 --- a/frontend/js/reducers/polochon.js +++ b/frontend/js/reducers/polochon.js @@ -1,28 +1,29 @@ -import { List, Map, fromJS } from "immutable" +import { List, Map, fromJS } from "immutable"; const defaultState = Map({ loadingPublic: false, loadingManaged: false, public: List(), - managed: List(), + managed: List() }); const handlers = { - "PUBLIC_POLOCHON_LIST_FETCH_PENDING": state => state.set("loadingPublic", true), - "PUBLIC_POLOCHON_LIST_FETCH_FULFILLED": (state, action) => { + PUBLIC_POLOCHON_LIST_FETCH_PENDING: state => state.set("loadingPublic", true), + PUBLIC_POLOCHON_LIST_FETCH_FULFILLED: (state, action) => { return state.merge({ loadingPublic: false, - public: List(fromJS(action.payload.response.data)), + public: List(fromJS(action.payload.response.data)) }); }, - "MANAGED_POLOCHON_LIST_FETCH_PENDING": state => state.set("loadingManaged", true), - "MANAGED_POLOCHON_LIST_FETCH_FULFILLED": (state, action) => { + MANAGED_POLOCHON_LIST_FETCH_PENDING: state => + state.set("loadingManaged", true), + MANAGED_POLOCHON_LIST_FETCH_FULFILLED: (state, action) => { return state.merge({ loadingManaged: false, - managed: List(fromJS(action.payload.response.data)), + managed: List(fromJS(action.payload.response.data)) }); - }, -} + } +}; export default (state = defaultState, action) => handlers[action.type] ? handlers[action.type](state, action) : state; diff --git a/frontend/js/reducers/show.js b/frontend/js/reducers/show.js index f748d3c..00149b9 100644 --- a/frontend/js/reducers/show.js +++ b/frontend/js/reducers/show.js @@ -1,35 +1,82 @@ -import { OrderedMap, Map, fromJS } from "immutable" +import { OrderedMap, Map, fromJS } from "immutable"; const defaultState = Map({ loading: false, show: Map({ - seasons: OrderedMap(), - }), + seasons: OrderedMap() + }) }); const handlers = { - "SHOW_FETCH_DETAILS_PENDING": state => state.set("loading", true), - "SHOW_FETCH_DETAILS_FULFILLED": (state, action) => sortEpisodes(state, action.payload.response.data), - "SHOW_UPDATE_STORE_WISHLIST": (state, action) => { - return state.mergeDeep(fromJS({ - "show": { - "tracked_season": action.payload.season, - "tracked_episode": action.payload.episode, - } - }))}, - "EPISODE_GET_DETAILS_PENDING": (state, action) => state.setIn(["show", "seasons", action.payload.main.season, action.payload.main.episode, "fetching"], true), - "EPISODE_GET_DETAILS_FULFILLED": (state, action) => { - let data = action.payload.response.data; - if (!data) { return state } - data.fetching = false; - return state.setIn(["show", "seasons", data.season, data.episode], fromJS(data)); + SHOW_FETCH_DETAILS_PENDING: state => state.set("loading", true), + SHOW_FETCH_DETAILS_FULFILLED: (state, action) => + sortEpisodes(state, action.payload.response.data), + SHOW_UPDATE_STORE_WISHLIST: (state, action) => { + return state.mergeDeep( + fromJS({ + show: { + tracked_season: action.payload.season, + tracked_episode: action.payload.episode + } + }) + ); }, - "EPISODE_SUBTITLES_UPDATE_PENDING" : (state, action) => - state.setIn(["show", "seasons", action.payload.main.season, action.payload.main.episode, "fetchingSubtitles"], true), - "EPISODE_SUBTITLES_UPDATE_FULFILLED": (state, action) => - state.setIn(["show", "seasons", action.payload.main.season, action.payload.main.episode, "subtitles"], fromJS(action.payload.response.data)) - .setIn(["show", "seasons", action.payload.main.season, action.payload.main.episode, "fetchingSubtitles"], false), -} + EPISODE_GET_DETAILS_PENDING: (state, action) => + state.setIn( + [ + "show", + "seasons", + action.payload.main.season, + action.payload.main.episode, + "fetching" + ], + true + ), + EPISODE_GET_DETAILS_FULFILLED: (state, action) => { + let data = action.payload.response.data; + if (!data) { + return state; + } + data.fetching = false; + return state.setIn( + ["show", "seasons", data.season, data.episode], + fromJS(data) + ); + }, + EPISODE_SUBTITLES_UPDATE_PENDING: (state, action) => + state.setIn( + [ + "show", + "seasons", + action.payload.main.season, + action.payload.main.episode, + "fetchingSubtitles" + ], + true + ), + EPISODE_SUBTITLES_UPDATE_FULFILLED: (state, action) => + state + .setIn( + [ + "show", + "seasons", + action.payload.main.season, + action.payload.main.episode, + "subtitles" + ], + fromJS(action.payload.response.data) + ) + .setIn( + [ + "show", + "seasons", + action.payload.main.season, + action.payload.main.episode, + "fetchingSubtitles" + ], + false + ) +}; const sortEpisodes = (state, show) => { let episodes = show.episodes; @@ -52,19 +99,19 @@ const sortEpisodes = (state, show) => { // Sort the episodes ret = ret.updateIn(["show", "seasons"], function(seasons) { return seasons.map(function(episodes) { - return episodes.sort((a,b) => a.get("episode") - b.get("episode")); + return episodes.sort((a, b) => a.get("episode") - b.get("episode")); }); }); // Sort the seasons ret = ret.updateIn(["show", "seasons"], function(seasons) { - return seasons.sort(function(a,b) { + return seasons.sort(function(a, b) { return a.first().get("season") - b.first().get("season"); }); }); - return ret -} + return ret; +}; export default (state = defaultState, action) => handlers[action.type] ? handlers[action.type](state, action) : state; diff --git a/frontend/js/reducers/shows.js b/frontend/js/reducers/shows.js index 9c38e80..ae9816a 100644 --- a/frontend/js/reducers/shows.js +++ b/frontend/js/reducers/shows.js @@ -1,4 +1,4 @@ -import { OrderedMap, Map, fromJS } from "immutable" +import { OrderedMap, Map, fromJS } from "immutable"; const defaultState = Map({ loading: false, @@ -6,14 +6,14 @@ const defaultState = Map({ filter: "", selectedImdbId: "", lastFetchUrl: "", - exploreOptions: Map(), + exploreOptions: Map() }); const handlers = { - "SHOW_LIST_FETCH_PENDING": state => state.set("loading", true), - "SHOW_LIST_FETCH_FULFILLED": (state, action) => { + SHOW_LIST_FETCH_PENDING: state => state.set("loading", true), + SHOW_LIST_FETCH_FULFILLED: (state, action) => { let shows = Map(); - action.payload.response.data.map(function (show) { + action.payload.response.data.map(function(show) { show.fetchingDetails = false; show.fetchingSubtitles = false; shows = shows.set(show.imdb_id, fromJS(show)); @@ -22,26 +22,30 @@ const handlers = { let selectedImdbId = ""; if (shows.size > 0) { // Sort by year - shows = shows.sort((a,b) => b.get("year") - a.get("year")); + shows = shows.sort((a, b) => b.get("year") - a.get("year")); selectedImdbId = shows.first().get("imdb_id"); } - return state.delete("shows").merge(Map({ - shows: shows, - filter: "", - loading: false, - selectedImdbId: selectedImdbId, - })); + return state.delete("shows").merge( + Map({ + shows: shows, + filter: "", + loading: false, + selectedImdbId: selectedImdbId + }) + ); }, - "SHOW_GET_DETAILS_PENDING": (state, action) => state.setIn(["shows", action.payload.main.imdbId, "fetchingDetails"], true), - "SHOW_GET_DETAILS_FULFILLED": (state, action) => { + SHOW_GET_DETAILS_PENDING: (state, action) => + state.setIn(["shows", action.payload.main.imdbId, "fetchingDetails"], true), + SHOW_GET_DETAILS_FULFILLED: (state, action) => { let show = action.payload.response.data; show.fetchingDetails = false; show.fetchingSubtitles = false; return state.setIn(["shows", show.imdb_id], fromJS(show)); }, - "SHOW_GET_EXPLORE_OPTIONS_FULFILLED": (state, action) => state.set("exploreOptions", fromJS(action.payload.response.data)), - "SHOW_UPDATE_STORE_WISHLIST": (state, action) => { + SHOW_GET_EXPLORE_OPTIONS_FULFILLED: (state, action) => + state.set("exploreOptions", fromJS(action.payload.response.data)), + SHOW_UPDATE_STORE_WISHLIST: (state, action) => { let season = action.payload.season; let episode = action.payload.episode; if (action.payload.wishlisted) { @@ -53,15 +57,21 @@ const handlers = { } } - return state.mergeIn(["shows", action.payload.imdbId], Map({ - "tracked_season": season, - "tracked_episode": episode, - })); + return state.mergeIn( + ["shows", action.payload.imdbId], + Map({ + tracked_season: season, + tracked_episode: episode + }) + ); }, - "UPDATE_LAST_SHOWS_FETCH_URL": (state, action) => state.set("lastFetchUrl", action.payload.url), - "SELECT_SHOW": (state, action) => state.set("selectedImdbId", action.payload.imdbId), - "SHOWS_UPDATE_FILTER": (state, action) => state.set("filter", action.payload.filter), -} + UPDATE_LAST_SHOWS_FETCH_URL: (state, action) => + state.set("lastFetchUrl", action.payload.url), + SELECT_SHOW: (state, action) => + state.set("selectedImdbId", action.payload.imdbId), + SHOWS_UPDATE_FILTER: (state, action) => + state.set("filter", action.payload.filter) +}; export default (state = defaultState, action) => handlers[action.type] ? handlers[action.type](state, action) : state; diff --git a/frontend/js/reducers/torrents.js b/frontend/js/reducers/torrents.js index d00f985..8efdbe2 100644 --- a/frontend/js/reducers/torrents.js +++ b/frontend/js/reducers/torrents.js @@ -1,24 +1,30 @@ -import { Map, List, fromJS } from "immutable" +import { Map, List, fromJS } from "immutable"; const defaultState = Map({ - "fetching": false, - "searching": false, - "torrents": List(), - "searchResults": List(), + fetching: false, + searching: false, + torrents: List(), + searchResults: List() }); const handlers = { - "TORRENTS_FETCH_PENDING": state => state.set("fetching", true), - "TORRENTS_FETCH_FULFILLED": (state, action) => state.merge(fromJS({ - fetching: false, - torrents: action.payload.response.data, - })), - "TORRENTS_SEARCH_PENDING": state => state.set("searching", true), - "TORRENTS_SEARCH_FULFILLED": (state, action) => state.merge(fromJS({ - searching: false, - searchResults: action.payload.response.data, - })), -} + TORRENTS_FETCH_PENDING: state => state.set("fetching", true), + TORRENTS_FETCH_FULFILLED: (state, action) => + state.merge( + fromJS({ + fetching: false, + torrents: action.payload.response.data + }) + ), + TORRENTS_SEARCH_PENDING: state => state.set("searching", true), + TORRENTS_SEARCH_FULFILLED: (state, action) => + state.merge( + fromJS({ + searching: false, + searchResults: action.payload.response.data + }) + ) +}; export default (state = defaultState, action) => handlers[action.type] ? handlers[action.type](state, action) : state; diff --git a/frontend/js/reducers/users.js b/frontend/js/reducers/users.js index 0812611..ba8de75 100644 --- a/frontend/js/reducers/users.js +++ b/frontend/js/reducers/users.js @@ -1,7 +1,7 @@ -import { Map, List, fromJS } from "immutable" +import { Map, List, fromJS } from "immutable"; -import jwtDecode from "jwt-decode" -import Cookies from "universal-cookie" +import jwtDecode from "jwt-decode"; +import Cookies from "universal-cookie"; const defaultState = Map({ error: "", @@ -18,52 +18,66 @@ const defaultState = Map({ polochonActivated: false, tokens: List(), modules: Map(), - modulesLoading: false, + modulesLoading: false }); -let initialState = defaultState +let initialState = defaultState; const token = localStorage.getItem("token"); if (token && token !== "") { - initialState = updateFromToken(initialState, token) + initialState = updateFromToken(initialState, token); } const handlers = { - "USER_LOGIN_PENDING": state => state.set("loading", true), - "USER_LOGIN_ERROR": (state, action) => { + USER_LOGIN_PENDING: state => state.set("loading", true), + USER_LOGIN_ERROR: (state, action) => { state.set("loading", false); return logoutUser(action.payload.response.message); }, - "USER_LOGIN_FULFILLED": (state, action) => { - return updateFromToken(state, action.payload.response.data.token) + USER_LOGIN_FULFILLED: (state, action) => { + return updateFromToken(state, action.payload.response.data.token); }, - "USER_SIGNUP_PENDING": state => state.set("loading", true), - "USER_SIGNUP_ERROR": (state, action) => state.merge(Map({ - error: action.payload.response.message, - loading: false, - })), - "USER_SIGNUP_FULFILLED": state => state.merge(Map({error: "", loading: false})), - "USER_SET_TOKEN": (state, action) => updateFromToken(state, action.payload.token), - "USER_LOGOUT": () => logoutUser(), - "GET_USER_PENDING": state => state.set("loading", true), - "GET_USER_FULFILLED": (state, action) => state.merge(Map({ - polochonToken: action.payload.response.data.token, - polochonUrl: action.payload.response.data.url, - polochonName: action.payload.response.data.name, - polochonId: action.payload.response.data.id, - polochonActivated: action.payload.response.data.activated, - loading: false, - })), - "GET_USER_TOKENS_PENDING": state => state.set("loading", true), - "GET_USER_TOKENS_FULFILLED": (state, action) => state.merge(Map({ - "tokens": fromJS(action.payload.response.data), - "loading": false, - })), - "GET_USER_MODULES_PENDING": state => state.set("modulesLoading", true), - "GET_USER_MODULES_FULFILLED": (state, action) => state.merge(Map({ - "modules": fromJS(action.payload.response.data), - "modulesLoading": false, - })), -} + USER_SIGNUP_PENDING: state => state.set("loading", true), + USER_SIGNUP_ERROR: (state, action) => + state.merge( + Map({ + error: action.payload.response.message, + loading: false + }) + ), + USER_SIGNUP_FULFILLED: state => + state.merge(Map({ error: "", loading: false })), + USER_SET_TOKEN: (state, action) => + updateFromToken(state, action.payload.token), + USER_LOGOUT: () => logoutUser(), + GET_USER_PENDING: state => state.set("loading", true), + GET_USER_FULFILLED: (state, action) => + state.merge( + Map({ + polochonToken: action.payload.response.data.token, + polochonUrl: action.payload.response.data.url, + polochonName: action.payload.response.data.name, + polochonId: action.payload.response.data.id, + polochonActivated: action.payload.response.data.activated, + loading: false + }) + ), + GET_USER_TOKENS_PENDING: state => state.set("loading", true), + GET_USER_TOKENS_FULFILLED: (state, action) => + state.merge( + Map({ + tokens: fromJS(action.payload.response.data), + loading: false + }) + ), + GET_USER_MODULES_PENDING: state => state.set("modulesLoading", true), + GET_USER_MODULES_FULFILLED: (state, action) => + state.merge( + Map({ + modules: fromJS(action.payload.response.data), + modulesLoading: false + }) + ) +}; function logoutUser(error) { localStorage.removeItem("token"); @@ -72,7 +86,7 @@ function logoutUser(error) { if (error !== "") { return defaultState.set("error", error); } else { - return defaultState + return defaultState; } } @@ -83,14 +97,16 @@ function updateFromToken(state, token) { const cookies = new Cookies(); cookies.set("token", token); - return state.merge(Map({ - error: "", - isLogged: true, - isTokenSet: true, - isAdmin: decodedToken.isAdmin, - isActivated: decodedToken.isActivated, - username: decodedToken.username, - })) + return state.merge( + Map({ + error: "", + isLogged: true, + isTokenSet: true, + isAdmin: decodedToken.isAdmin, + isActivated: decodedToken.isActivated, + username: decodedToken.username + }) + ); } export default (state = initialState, action) => diff --git a/frontend/js/requests.js b/frontend/js/requests.js index 5512bb4..1a11f38 100644 --- a/frontend/js/requests.js +++ b/frontend/js/requests.js @@ -1,4 +1,4 @@ -import axios from "axios" +import axios from "axios"; // This functions returns an axios instance, the token is added to the // configuration if found in the localStorage @@ -6,17 +6,22 @@ export function configureAxios(headers = {}) { // Get the token from the localStorate const token = localStorage.getItem("token"); if (token) { - headers = { "Authorization": `Bearer ${token}` }; + headers = { Authorization: `Bearer ${token}` }; } return axios.create({ headers - }) + }); } // This function takes en event prefix to dispatch evens during the life of the // request, it also take a promise (axios request) -export function request(eventPrefix, promise, callbackEvents = null, mainPayload = null) { +export function request( + eventPrefix, + promise, + callbackEvents = null, + mainPayload = null +) { // Events const pending = `${eventPrefix}_PENDING`; const fulfilled = `${eventPrefix}_FULFILLED`; @@ -26,60 +31,59 @@ export function request(eventPrefix, promise, callbackEvents = null, mainPayload dispatch({ type: pending, payload: { - main: mainPayload, + main: mainPayload } - }) + }); return promise - .then(response => { - if (response.data.status === "error") - { + .then(response => { + if (response.data.status === "error") { + dispatch({ + type: "ADD_ALERT_ERROR", + payload: { + message: response.data.message, + main: mainPayload + } + }); + dispatch({ + type: errored, + payload: { + response: response.data, + main: mainPayload + } + }); + return; + } + dispatch({ + type: fulfilled, + payload: { + response: response.data, + main: mainPayload + } + }); + if (callbackEvents) { + for (let event of callbackEvents) { + if (typeof event === "function") { + event = event(); + } + dispatch(event); + } + } + }) + .catch(error => { + // Unauthorized + if (error.response && error.response.status == 401) { + dispatch({ + type: "USER_LOGOUT" + }); + } dispatch({ type: "ADD_ALERT_ERROR", payload: { - message: response.data.message, - main: mainPayload, + message: error.response.data, + main: mainPayload } }); - dispatch({ - type: errored, - payload: { - response: response.data, - main: mainPayload, - }, - }) - return; - } - dispatch({ - type: fulfilled, - payload: { - response: response.data, - main: mainPayload, - }, - }) - if (callbackEvents) { - for (let event of callbackEvents) { - if (typeof event === "function") { - event = event(); - } - dispatch(event); - } - } - }) - .catch(error => { - // Unauthorized - if (error.response && error.response.status == 401) { - dispatch({ - type: "USER_LOGOUT", - }) - } - dispatch({ - type: "ADD_ALERT_ERROR", - payload: { - message: error.response.data, - main: mainPayload, - } - }) - }) - } + }); + }; } diff --git a/frontend/js/store.js b/frontend/js/store.js index a354044..f7e7179 100644 --- a/frontend/js/store.js +++ b/frontend/js/store.js @@ -17,12 +17,7 @@ if (process.env.NODE_ENV === "development") { // Export the store const store = createStore( rootReducer, - compose( - applyMiddleware( - ...middlewares, - ), - ), + compose(applyMiddleware(...middlewares)) ); export default store; - diff --git a/frontend/js/utils.js b/frontend/js/utils.js index 95e6d73..deca39c 100644 --- a/frontend/js/utils.js +++ b/frontend/js/utils.js @@ -1,65 +1,70 @@ -export const prettyDurationFromMinutes = (runtime) => { +export const prettyDurationFromMinutes = runtime => { const hours = Math.floor(runtime / 60); - const minutes = (runtime % 60); + const minutes = runtime % 60; let duration = ""; - if (hours > 0) { duration += hours + "h" } - if (minutes > 0) { duration += ("0" + minutes).slice(-2) } - if (hours === 0) { duration += " min" } + if (hours > 0) { + duration += hours + "h"; + } + if (minutes > 0) { + duration += ("0" + minutes).slice(-2); + } + if (hours === 0) { + duration += " min"; + } return duration; -} +}; -const pad = (d) => (d < 10) ? "0" + d.toString() : d.toString(); +const pad = d => (d < 10 ? "0" + d.toString() : d.toString()); export const prettyEpisodeName = (showName, season, episode) => `${showName} S${pad(season)}E${pad(episode)}`; -export const inLibrary = (element) => - element.get("polochon_url", "") !== ""; +export const inLibrary = element => element.get("polochon_url", "") !== ""; -export const isWishlisted = (element) => { - const wishlisted = element.get("wishlisted", undefined) +export const isWishlisted = element => { + const wishlisted = element.get("wishlisted", undefined); if (wishlisted !== undefined) { return wishlisted; } const trackedSeason = element.get("tracked_season", null); const trackedEpisode = element.get("tracked_episode", null); - if ((trackedSeason !== null) && (trackedEpisode !== null)) { + if (trackedSeason !== null && trackedEpisode !== null) { return true; } - return false -} + return false; +}; export const isEpisodeWishlisted = (element, trackedSeason, trackedEpisode) => { - if ((trackedSeason === null) && (trackedEpisode === null)) { + if (trackedSeason === null && trackedEpisode === null) { return false; } - if ((trackedSeason === 0) && (trackedEpisode === 0)) { - return true + if (trackedSeason === 0 && trackedEpisode === 0) { + return true; } const season = element.get("season", 0); const episode = element.get("episode", 0); if (season < trackedSeason) { - return false + return false; } else if (season > trackedSeason) { - return true + return true; } else { - return (episode >= trackedEpisode) + return episode >= trackedEpisode; } -} +}; -export const prettySize = (fileSizeInBytes) => { - var i = -1; - var byteUnits = [" kB", " MB", " GB", " TB", "PB", "EB", "ZB", "YB"]; - do { - fileSizeInBytes = fileSizeInBytes / 1024; - i++; - } while (fileSizeInBytes > 1024); +export const prettySize = fileSizeInBytes => { + var i = -1; + var byteUnits = [" kB", " MB", " GB", " TB", "PB", "EB", "ZB", "YB"]; + do { + fileSizeInBytes = fileSizeInBytes / 1024; + i++; + } while (fileSizeInBytes > 1024); - return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i]; -} + return Math.max(fileSizeInBytes, 0.1).toFixed(1) + byteUnits[i]; +}; diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js index c021fc4..cc3ac21 100644 --- a/frontend/postcss.config.js +++ b/frontend/postcss.config.js @@ -1,5 +1,3 @@ module.exports = { - plugins: [ - require("autoprefixer") - ] -} + plugins: [require("autoprefixer")] +}; diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js index 75efc5d..ffd0f54 100644 --- a/frontend/webpack.config.js +++ b/frontend/webpack.config.js @@ -1,6 +1,6 @@ var webpack = require("webpack"); var path = require("path"); -var WebpackPwaManifest = require("webpack-pwa-manifest") +var WebpackPwaManifest = require("webpack-pwa-manifest"); var HtmlWebpackPlugin = require("html-webpack-plugin"); var { CleanWebpackPlugin } = require("clean-webpack-plugin"); @@ -19,7 +19,7 @@ const config = { entry: path.join(SRC_DIR, "js/app.js"), output: { path: BUILD_DIR, - filename: "[contenthash]-app.js", + filename: "[contenthash]-app.js" }, optimization: { runtimeChunk: "single", @@ -28,10 +28,10 @@ const config = { vendor: { test: /[\\/]node_modules[\\/]/, name: "vendors", - chunks: "all", - }, - }, - }, + chunks: "all" + } + } + } }, module: { rules: [ @@ -47,44 +47,39 @@ const config = { }, { test: /\.scss$/, - use: [ - "style-loader", - "css-loader", - "sass-loader", - "postcss-loader", - ], + use: ["style-loader", "css-loader", "sass-loader", "postcss-loader"] }, { test: /\.(png|jpg|svg|ico)$/, - use: ["file-loader?name=[hash]-[name].[ext]"], + use: ["file-loader?name=[hash]-[name].[ext]"] }, { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, - use: ["url-loader?limit=10000&mimetype=application/font-woff"], + use: ["url-loader?limit=10000&mimetype=application/font-woff"] }, { test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/, - use: ["file-loader"], + use: ["file-loader"] } ] }, plugins: [ new webpack.DefinePlugin({ - "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV), + "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV) }), new webpack.HashedModuleIdsPlugin(), new CleanWebpackPlugin({ - cleanOnceBeforeBuildPatterns: ["**/*", "!img/**/*", "!img"], + cleanOnceBeforeBuildPatterns: ["**/*", "!img/**/*", "!img"] }), new HtmlWebpackPlugin({ - template: path.join(SRC_DIR, "index.html"), + template: path.join(SRC_DIR, "index.html") }), new WebpackPwaManifest({ fingerprints: true, inject: true, ios: { "apple-mobile-web-app-status-bar-style": "default", - "apple-mobile-web-app-title": "Canapé", + "apple-mobile-web-app-title": "Canapé" }, name: "Canapé", short_name: "Canapé", @@ -97,23 +92,23 @@ const config = { icons: [ { src: path.resolve(__dirname, "img/android-chrome-512x512.png"), - sizes: [96, 128, 192, 256, 384, 512], + sizes: [96, 128, 192, 256, 384, 512] }, { src: path.resolve(__dirname, "img/apple-touch-icon.png"), sizes: [80, 120, 152, 167, 180], ios: true - }, - ], - }), + } + ] + }) ], resolve: { - extensions: [".js"], - }, + extensions: [".js"] + } }; if (process.env.NODE_ENV !== "production") { - config.devtool = "#cheap-module-source-map" + config.devtool = "#cheap-module-source-map"; } module.exports = config;