diff --git a/src/internal/shows/shows.go b/src/internal/shows/shows.go
index cd5475c..cecf755 100644
--- a/src/internal/shows/shows.go
+++ b/src/internal/shows/shows.go
@@ -80,12 +80,12 @@ var (
type Show struct {
sqly.BaseModel
polochon.Show
- Episodes []*Episode
- TrackedSeason int
- TrackedEpisode int
- BannerURL string `json:"banner_url"`
- FanartURL string `json:"fanart_url"`
- PosterURL string `json:"poster_url"`
+ Episodes []*Episode `json:"episodes"`
+ TrackedSeason int `json:"tracked_season"`
+ TrackedEpisode int `json:"tracked_episode"`
+ BannerURL string `json:"banner_url"`
+ FanartURL string `json:"fanart_url"`
+ PosterURL string `json:"poster_url"`
}
// ShowDB represents the Show in the DB
@@ -100,7 +100,6 @@ type ShowDB struct {
FirstAired time.Time `db:"first_aired"`
Created time.Time `db:"created_at"`
Updated time.Time `db:"updated_at"`
- // URL string `json:"-"`
}
// NewShowDB returns a Show ready to be put in DB from a
@@ -248,7 +247,7 @@ func (s *Show) GetDetails(env *web.Env, force bool) error {
// GetPosterURL returns the image URL or the default image if the poster is not yet downloaded
func (s *Show) GetPosterURL(env *web.Env) string {
// Check if the movie image exists
- if _, err := os.Stat(s.imgURL(env, "poster")); os.IsNotExist(err) {
+ if _, err := os.Stat(s.imgFile(env, "poster")); os.IsNotExist(err) {
// TODO image in the config ?
return "img/noimage.png"
}
@@ -273,11 +272,16 @@ func (s *Show) downloadImages(env *web.Env) {
}
// imgFile returns the image location on disk
-func (s *Show) imgURL(env *web.Env, imgType string) string {
+func (s *Show) imgFile(env *web.Env, imgType string) string {
fileURL := fmt.Sprintf("img/shows/%s-%s.jpg", s.ImdbID, imgType)
return filepath.Join(env.Config.PublicDir, fileURL)
}
+// imgURL returns the default image url
+func (s *Show) imgURL(env *web.Env, imgType string) string {
+ return fmt.Sprintf("img/shows/%s-%s.jpg", s.ImdbID, imgType)
+}
+
// GetDetailsAsUser like GetDetails but with User context
func (s *Show) GetDetailsAsUser(db *sqlx.DB, user *users.User, log *logrus.Entry) error {
var err error
diff --git a/src/public/js/actions/actionCreators.js b/src/public/js/actions/actionCreators.js
index a3d41dc..e0c1665 100644
--- a/src/public/js/actions/actionCreators.js
+++ b/src/public/js/actions/actionCreators.js
@@ -1,18 +1,8 @@
import { configureAxios, request } from '../requests'
-// Select Movie
-export function selectMovie(imdbId) {
- return {
- type: 'SELECT_MOVIE',
- imdbId
- }
-}
-
-export function isUserLoggedIn() {
- return {
- type: 'IS_USER_LOGGED_IN',
- }
-}
+// ======================
+// Errors
+// ======================
export function addError(message) {
return {
@@ -29,12 +19,22 @@ export function dismissError() {
}
}
+// ======================
+// Users
+// ======================
+
export function userLogout() {
return {
type: 'USER_LOGOUT',
}
}
+export function isUserLoggedIn() {
+ return {
+ type: 'IS_USER_LOGGED_IN',
+ }
+}
+
export function loginUser(username, password) {
return request(
'USER_LOGIN',
@@ -69,6 +69,17 @@ export function getUserInfos() {
)
}
+// ======================
+// Movies
+// ======================
+
+export function selectMovie(imdbId) {
+ return {
+ type: 'SELECT_MOVIE',
+ imdbId
+ }
+}
+
export function getMovieDetails(imdbId) {
return request(
'MOVIE_GET_DETAILS',
@@ -82,3 +93,28 @@ export function fetchMovies(url) {
configureAxios().get(url)
)
}
+
+// ======================
+// Shows
+// ======================
+
+export function fetchShows(url) {
+ return request(
+ 'SHOW_LIST_FETCH',
+ configureAxios().get(url)
+ )
+}
+
+export function fetchShowDetails(imdbId) {
+ return request(
+ 'SHOW_FETCH_DETAILS',
+ configureAxios().get(`/shows/${imdbId}`)
+ )
+}
+
+export function selectShow(imdbId) {
+ return {
+ type: 'SELECT_SHOW',
+ imdbId
+ }
+}
diff --git a/src/public/js/app.js b/src/public/js/app.js
index 7a0a242..b75f21e 100644
--- a/src/public/js/app.js
+++ b/src/public/js/app.js
@@ -29,6 +29,8 @@ import store, { history } from './store'
import NavBar from './components/navbar'
import Error from './components/errors'
import MovieList from './components/movies/list'
+import ShowList from './components/shows/list'
+import ShowDetails from './components/shows/details'
import UserLoginForm from './components/users/login'
import UserEdit from './components/users/edit'
import UserSignUp from './components/users/signup'
@@ -53,6 +55,7 @@ class Main extends React.Component {
function mapStateToProps(state) {
return {
movieStore: state.movieStore,
+ showStore: state.showStore,
userStore: state.userStore,
errors: state.errors,
}
@@ -81,6 +84,14 @@ const MovieListPolochon = (props) => (
)
+const ShowListPopular = (props) => (
+
+)
+
+const ShowDetailsView = (props) => (
+
+)
+
ReactDOM.render((
@@ -91,6 +102,8 @@ ReactDOM.render((
+
+
diff --git a/src/public/js/components/list/details.js b/src/public/js/components/list/details.js
new file mode 100644
index 0000000..12ca5e8
--- /dev/null
+++ b/src/public/js/components/list/details.js
@@ -0,0 +1,24 @@
+import React from 'react'
+
+export default function ListDetails(props) {
+ return (
+
+
+
{props.data.title}
+
{props.data.title}
+ {props.data.runtime &&
+
+
+ {props.data.runtime} min
+
+ }
+
+
+ {props.data.rating} ({props.data.votes} counts)
+
+
{props.data.plot}
+
+ {props.children}
+
+ );
+}
diff --git a/src/public/js/components/list/filter.js b/src/public/js/components/list/filter.js
new file mode 100644
index 0000000..8396379
--- /dev/null
+++ b/src/public/js/components/list/filter.js
@@ -0,0 +1,22 @@
+import React from 'react'
+import { Control, Form } from 'react-redux-form';
+
+export default function ListFilter(props) {
+ return (
+
+ );
+}
diff --git a/src/public/js/components/list/poster.js b/src/public/js/components/list/poster.js
new file mode 100644
index 0000000..e5f8d57
--- /dev/null
+++ b/src/public/js/components/list/poster.js
@@ -0,0 +1,16 @@
+import React from 'react'
+
+export default function ListPoster(props) {
+ const selected = props.selected ? ' thumbnail-selected' : '';
+ const imgClass = 'thumbnail' + selected;
+ return (
+
+ );
+}
diff --git a/src/public/js/components/list/posters.js b/src/public/js/components/list/posters.js
new file mode 100644
index 0000000..2514a56
--- /dev/null
+++ b/src/public/js/components/list/posters.js
@@ -0,0 +1,45 @@
+import React from 'react'
+import fuzzy from 'fuzzy';
+
+import ListFilter from './filter'
+import ListPoster from './poster'
+
+export default function ListPosters(props) {
+ let elmts = props.data.slice();
+
+ // Filter the list of elements
+ if (props.filter !== "") {
+ const filtered = fuzzy.filter(props.filter, elmts, {
+ extract: (el) => el.title
+ });
+ elmts = filtered.map((el) => el.original);
+ }
+
+ // Limit the number of results
+ if (elmts.length > props.perPage) {
+ elmts = elmts.slice(0, props.perPage);
+ }
+
+ return (
+
+
+
+ {elmts.map(function(el, index) {
+ const selected = (el.imdb_id === props.selectedImdbId) ? true : false;
+ return (
+ props.onClick(el.imdb_id)}
+ />
+ )}
+ )}
+
+
+ );
+}
diff --git a/src/public/js/components/movies/list.js b/src/public/js/components/movies/list.js
index 4ec4dd0..c1b4731 100644
--- a/src/public/js/components/movies/list.js
+++ b/src/public/js/components/movies/list.js
@@ -1,101 +1,7 @@
import React from 'react'
-import axios from 'axios'
-import { Control, Form } from 'react-redux-form';
-import fuzzy from 'fuzzy';
-function MoviePosters(props) {
- let movies = props.movies.slice();
-
- // Filter the movies
- if (props.filter !== "") {
- const filtered = fuzzy.filter(props.filter, movies, {
- extract: (el) => el.title
- });
- movies = filtered.map((el) => el.original);
- }
-
- // Limit the number of results
- if (movies.length > props.perPage) {
- movies = movies.slice(0, props.perPage);
- }
-
- return (
-
-
-
- {movies.map(function(movie, index) {
- const selected = (movie.imdb_id === props.selectedMovieId) ? true : false;
- return (
- props.onClick(movie.imdb_id)}
- />
- )}
- )}
-
-
- );
-}
-
-class MovieListFilter extends React.Component {
- render() {
- return (
-
- );
- }
-}
-
-function MoviePoster(props) {
- const selected = props.selected ? ' thumbnail-selected' : '';
- const imgClass = 'thumbnail' + selected;
- return (
-
- );
-}
-
-function MovieDetails(props) {
- return (
-
-
-
{props.movie.title}
-
{props.movie.title}
-
-
- {props.movie.runtime} min
-
-
-
- {props.movie.rating} ({props.movie.votes} counts)
-
-
{props.movie.plot}
-
-
-
- );
-}
+import ListPosters from '../list/posters'
+import ListDetails from '../list/details'
class MovieButtons extends React.Component {
constructor(props) {
@@ -112,7 +18,7 @@ class MovieButtons extends React.Component {
render() {
const imdb_link = `http://www.imdb.com/title/${this.props.movie.imdb_id}`;
return (
-
+
{this.props.fetching ||
@@ -159,19 +65,24 @@ export default class MovieList extends React.Component {
const selectedMovie = movies[index];
return (
-
{selectedMovie &&
-
+
+
+
}
);
diff --git a/src/public/js/components/navbar.js b/src/public/js/components/navbar.js
index 859ca48..fd25207 100644
--- a/src/public/js/components/navbar.js
+++ b/src/public/js/components/navbar.js
@@ -27,6 +27,9 @@ export default class NavBar extends React.Component {
Polochon movies
+
+ Polochon shows
+