From 1e1abf407c67565b36b5079a8276c03dd00c1a24 Mon Sep 17 00:00:00 2001
From: Ruud <ruud@crashdummy.nl>
Date: Mon, 4 Mar 2013 23:02:51 +0100
Subject: [PATCH] Dashboard

---
 couchpotato/core/_base/clientscript/main.py   |   1 +
 couchpotato/core/helpers/variable.py          |   2 +-
 couchpotato/core/plugins/base.py              |   1 -
 couchpotato/core/plugins/browser/main.py      |   4 +-
 .../core/plugins/dashboard/__init__.py        |   6 +
 couchpotato/core/plugins/dashboard/main.py    | 120 ++++++++
 couchpotato/core/plugins/file/static/file.js  |   1 +
 couchpotato/core/plugins/movie/main.py        | 104 +++++--
 couchpotato/core/plugins/movie/static/list.js |  80 ++---
 .../core/plugins/movie/static/movie.css       | 289 +++++++++++++-----
 .../core/plugins/movie/static/movie.js        | 142 +++++----
 .../core/plugins/movie/static/search.css      |   2 +
 couchpotato/core/plugins/searcher/main.py     |   7 +-
 couchpotato/static/scripts/couchpotato.js     |  13 +-
 couchpotato/static/scripts/page/home.js       |  91 ++++++
 couchpotato/static/scripts/page/manage.js     |   4 +-
 couchpotato/static/style/main.css             |   6 +
 17 files changed, 654 insertions(+), 219 deletions(-)
 create mode 100644 couchpotato/core/plugins/dashboard/__init__.py
 create mode 100644 couchpotato/core/plugins/dashboard/main.py
 create mode 100644 couchpotato/static/scripts/page/home.js

diff --git a/couchpotato/core/_base/clientscript/main.py b/couchpotato/core/_base/clientscript/main.py
index fd5ca6a6..f2a30f6f 100644
--- a/couchpotato/core/_base/clientscript/main.py
+++ b/couchpotato/core/_base/clientscript/main.py
@@ -40,6 +40,7 @@ class ClientScript(Plugin):
             'scripts/block/navigation.js',
             'scripts/block/footer.js',
             'scripts/block/menu.js',
+            'scripts/page/home.js',
             'scripts/page/wanted.js',
             'scripts/page/settings.js',
             'scripts/page/about.js',
diff --git a/couchpotato/core/helpers/variable.py b/couchpotato/core/helpers/variable.py
index 1ecb35bf..82bf88f7 100644
--- a/couchpotato/core/helpers/variable.py
+++ b/couchpotato/core/helpers/variable.py
@@ -168,4 +168,4 @@ def randomString(size = 8, chars = string.ascii_uppercase + string.digits):
     return ''.join(random.choice(chars) for x in range(size))
 
 def splitString(str, split_on = ','):
-    return [x.strip() for x in str.split(split_on)]
+    return [x.strip() for x in str.split(split_on)] if str else []
diff --git a/couchpotato/core/plugins/base.py b/couchpotato/core/plugins/base.py
index edecaa94..9330631d 100644
--- a/couchpotato/core/plugins/base.py
+++ b/couchpotato/core/plugins/base.py
@@ -240,7 +240,6 @@ class Plugin(object):
                     del kwargs['cache_timeout']
 
                 data = self.urlopen(url, **kwargs)
-
                 if data:
                     self.setCache(cache_key, data, timeout = cache_timeout)
                 return data
diff --git a/couchpotato/core/plugins/browser/main.py b/couchpotato/core/plugins/browser/main.py
index b5839e73..3eee85bb 100644
--- a/couchpotato/core/plugins/browser/main.py
+++ b/couchpotato/core/plugins/browser/main.py
@@ -15,7 +15,7 @@ if os.name == 'nt':
         raise ImportError("Missing the win32file module, which is a part of the prerequisite \
             pywin32 package. You can get it from http://sourceforge.net/projects/pywin32/files/pywin32/");
     else:
-        import win32file
+        import win32file #@UnresolvedImport
 
 class FileBrowser(Plugin):
 
@@ -98,7 +98,7 @@ class FileBrowser(Plugin):
 
     def has_hidden_attribute(self, filepath):
         try:
-            attrs = ctypes.windll.kernel32.GetFileAttributesW(unicode(filepath))
+            attrs = ctypes.windll.kernel32.GetFileAttributesW(unicode(filepath)) #@UndefinedVariable
             assert attrs != -1
             result = bool(attrs & 2)
         except (AttributeError, AssertionError):
diff --git a/couchpotato/core/plugins/dashboard/__init__.py b/couchpotato/core/plugins/dashboard/__init__.py
new file mode 100644
index 00000000..81279291
--- /dev/null
+++ b/couchpotato/core/plugins/dashboard/__init__.py
@@ -0,0 +1,6 @@
+from .main import Dashboard
+
+def start():
+    return Dashboard()
+
+config = []
diff --git a/couchpotato/core/plugins/dashboard/main.py b/couchpotato/core/plugins/dashboard/main.py
new file mode 100644
index 00000000..d5f9ef0b
--- /dev/null
+++ b/couchpotato/core/plugins/dashboard/main.py
@@ -0,0 +1,120 @@
+from couchpotato import get_session
+from couchpotato.api import addApiView
+from couchpotato.core.event import fireEvent
+from couchpotato.core.helpers.request import jsonified, getParams
+from couchpotato.core.helpers.variable import splitString, tryInt
+from couchpotato.core.logger import CPLog
+from couchpotato.core.plugins.base import Plugin
+from couchpotato.core.settings.model import Movie
+from sqlalchemy.sql.expression import or_
+import random
+
+log = CPLog(__name__)
+
+
+class Dashboard(Plugin):
+
+    def __init__(self):
+
+        addApiView('dashboard.suggestions', self.suggestView)
+        addApiView('dashboard.soon', self.getSoonView)
+
+    def newSuggestions(self):
+
+        movies = fireEvent('movie.list', status = ['active', 'done'], limit_offset = (20, 0), single = True)
+        movie_identifiers = [m['library']['identifier'] for m in movies[1]]
+
+        ignored_movies = fireEvent('movie.list', status = ['ignored', 'deleted'], limit_offset = (100, 0), single = True)
+        ignored_identifiers = [m['library']['identifier'] for m in ignored_movies[1]]
+
+        suggestions = fireEvent('movie.suggest', movies = movie_identifiers, ignore = ignored_identifiers, single = True)
+        suggest_status = fireEvent('status.get', 'suggest', single = True)
+
+        for suggestion in suggestions:
+            fireEvent('movie.add', params = {'identifier': suggestion}, force_readd = False, search_after = False, status_id = suggest_status.get('id'))
+
+    def suggestView(self):
+
+        db = get_session()
+
+        movies = db.query(Movie).limit(20).all()
+        identifiers = [m.library.identifier for m in movies]
+
+        suggestions = fireEvent('movie.suggest', movies = identifiers, single = True)
+        print suggestions
+
+        return jsonified({
+            'result': True,
+            'suggestions': suggestions
+        })
+
+    def getSoonView(self):
+
+        params = getParams()
+        db = get_session()
+
+        # Get profiles first, determine pre or post theater
+        profiles = fireEvent('profile.all', single = True)
+        qualities = fireEvent('quality.all', single = True)
+        pre_releases = fireEvent('quality.pre_releases', single = True)
+
+        id_pre = {}
+        for quality in qualities:
+            id_pre[quality.get('id')] = quality.get('identifier') in pre_releases
+
+        # See what the profile contain and cache it
+        profile_pre = {}
+        for profile in profiles:
+            contains = {}
+            for profile_type in profile.get('types', []):
+                contains['theater' if id_pre.get(profile_type.get('quality_id')) else 'dvd'] = True
+
+            profile_pre[profile.get('id')] = contains
+
+        # Get all active movies
+        q = db.query(Movie) \
+            .join(Movie.profile, Movie.library) \
+            .filter(or_(*[Movie.status.has(identifier = s) for s in ['active']])) \
+            .group_by(Movie.id)
+
+        # Add limit
+        limit_offset = params.get('limit_offset')
+        limit = 12
+        if limit_offset:
+            splt = splitString(limit_offset) if isinstance(limit_offset, (str, unicode)) else limit_offset
+            limit = tryInt(splt[0])
+
+        all_movies = q.all()
+
+        if params.get('random', False):
+            random.shuffle(all_movies)
+
+        movies = []
+        for movie in all_movies:
+            pp = profile_pre.get(movie.profile.id)
+            eta = movie.library.info.get('release_date', {})
+            coming_soon = False
+
+            # Theater quality
+            if pp.get('theater') and fireEvent('searcher.could_be_released', True, eta, single = True):
+                coming_soon = True
+            if pp.get('dvd') and fireEvent('searcher.could_be_released', False, eta, single = True):
+                coming_soon = True
+
+            if coming_soon:
+                temp = movie.to_dict({
+                    'profile': {'types': {}},
+                    'releases': {'files':{}, 'info': {}},
+                    'library': {'titles': {}, 'files':{}},
+                    'files': {},
+                })
+                movies.append(temp)
+
+                if len(movies) >= limit:
+                    break
+
+        return jsonified({
+            'success': True,
+            'empty': len(movies) == 0,
+            'movies': movies,
+        })
diff --git a/couchpotato/core/plugins/file/static/file.js b/couchpotato/core/plugins/file/static/file.js
index 2093e2fe..7b893e88 100644
--- a/couchpotato/core/plugins/file/static/file.js
+++ b/couchpotato/core/plugins/file/static/file.js
@@ -4,6 +4,7 @@ var File = new Class({
 		var self = this;
 
 		if(!file){
+			self.empty = true;
 			self.el = new Element('div');
 			return
 		}
diff --git a/couchpotato/core/plugins/movie/main.py b/couchpotato/core/plugins/movie/main.py
index 0e942f09..c708ec4e 100644
--- a/couchpotato/core/plugins/movie/main.py
+++ b/couchpotato/core/plugins/movie/main.py
@@ -6,10 +6,11 @@ from couchpotato.core.helpers.request import getParams, jsonified, getParam
 from couchpotato.core.helpers.variable import getImdb, splitString
 from couchpotato.core.logger import CPLog
 from couchpotato.core.plugins.base import Plugin
-from couchpotato.core.settings.model import Library, LibraryTitle, Movie
+from couchpotato.core.settings.model import Library, LibraryTitle, Movie, \
+    Release
 from couchpotato.environment import Env
 from sqlalchemy.orm import joinedload_all
-from sqlalchemy.sql.expression import or_, asc, not_
+from sqlalchemy.sql.expression import or_, asc, not_, desc
 from string import ascii_lowercase
 
 log = CPLog(__name__)
@@ -41,6 +42,7 @@ class MoviePlugin(Plugin):
             'desc': 'List movies in wanted list',
             'params': {
                 'status': {'type': 'array or csv', 'desc': 'Filter movie by status. Example:"active,done"'},
+                'release_status': {'type': 'array or csv', 'desc': 'Filter movie by status of its releases. Example:"snatched,available"'},
                 'limit_offset': {'desc': 'Limit and offset the movie list. Examples: "50" or "50,30"'},
                 'starts_with': {'desc': 'Starts with these characters. Example: "a" returns all movies starting with the letter "a"'},
                 'search': {'desc': 'Search movie title'},
@@ -94,6 +96,33 @@ class MoviePlugin(Plugin):
         addEvent('movie.list', self.list)
         addEvent('movie.restatus', self.restatus)
 
+        addEvent('app.load', self.cleanReleases)
+
+    def cleanReleases(self):
+
+        prop_name = 'cleaned_releases'
+        already_cleaned = Env.prop(prop_name, default = False)
+        if already_cleaned:
+            return True
+
+        log.info('Removing releases from library movies')
+
+        db = get_session()
+
+        movies = db.query(Movie).all()
+
+        done_status = fireEvent('status.get', 'done', single = True)
+        available_status = fireEvent('status.get', 'available', single = True)
+        snatched_status = fireEvent('status.get', 'snatched', single = True)
+
+        for movie in movies:
+            if movie.status_id == done_status.get('id'):
+                for rel in movie.releases:
+                    if rel.status_id in [available_status.get('id'), snatched_status.get('id')]:
+                        fireEvent('release.delete', id = rel.id, single = True)
+
+        Env.prop(prop_name, True)
+
     def getView(self):
 
         movie_id = getParam('id')
@@ -121,20 +150,29 @@ class MoviePlugin(Plugin):
 
         return results
 
-    def list(self, status = ['active'], limit_offset = None, starts_with = None, search = None):
+    def list(self, status = None, release_status = None, limit_offset = None, starts_with = None, search = None, order = None):
 
         db = get_session()
 
         # Make a list from string
-        if not isinstance(status, (list, tuple)):
+        if status and not isinstance(status, (list, tuple)):
             status = [status]
+        if release_status and not isinstance(release_status, (list, tuple)):
+            release_status = [release_status]
 
         q = db.query(Movie) \
-            .join(Movie.library, Library.titles) \
+            .outerjoin(Movie.releases, Movie.library, Library.titles) \
             .filter(LibraryTitle.default == True) \
-            .filter(or_(*[Movie.status.has(identifier = s) for s in status])) \
             .group_by(Movie.id)
 
+        # Filter on movie status
+        if status and len(status) > 0:
+            q = q.filter(or_(*[Movie.status.has(identifier = s) for s in status]))
+
+        # Filter on release status
+        if release_status and len(release_status) > 0:
+            q = q.filter(or_(*[Release.status.has(identifier = s) for s in release_status]))
+
         total_count = q.count()
 
         filter_or = []
@@ -154,7 +192,10 @@ class MoviePlugin(Plugin):
         if filter_or:
             q = q.filter(or_(*filter_or))
 
-        q = q.order_by(asc(LibraryTitle.simple_title))
+        if order == 'release_order':
+            q = q.order_by(desc(Release.last_edit))
+        else:
+            q = q.order_by(asc(LibraryTitle.simple_title))
 
         q = q.subquery()
         q2 = db.query(Movie).join((q, q.c.id == Movie.id)) \
@@ -166,7 +207,7 @@ class MoviePlugin(Plugin):
             .options(joinedload_all('files'))
 
         if limit_offset:
-            splt = splitString(limit_offset)
+            splt = splitString(limit_offset) if isinstance(limit_offset, (str, unicode)) else limit_offset
             limit = splt[0]
             offset = 0 if len(splt) is 1 else splt[1]
             q2 = q2.limit(limit).offset(offset)
@@ -185,7 +226,7 @@ class MoviePlugin(Plugin):
         #db.close()
         return (total_count, movies)
 
-    def availableChars(self, status = ['active']):
+    def availableChars(self, status = None, release_status = None):
 
         chars = ''
 
@@ -194,11 +235,20 @@ class MoviePlugin(Plugin):
         # Make a list from string
         if not isinstance(status, (list, tuple)):
             status = [status]
+        if release_status and not isinstance(release_status, (list, tuple)):
+            release_status = [release_status]
 
         q = db.query(Movie) \
-            .join(Movie.library, Library.titles, Movie.status) \
-            .options(joinedload_all('library.titles')) \
-            .filter(or_(*[Movie.status.has(identifier = s) for s in status]))
+            .outerjoin(Movie.releases, Movie.library, Library.titles, Movie.status) \
+            .options(joinedload_all('library.titles'))
+
+        # Filter on movie status
+        if status and len(status) > 0:
+            q = q.filter(or_(*[Movie.status.has(identifier = s) for s in status]))
+
+        # Filter on release status
+        if release_status and len(release_status) > 0:
+            q = q.filter(or_(*[Release.status.has(identifier = s) for s in release_status]))
 
         results = q.all()
 
@@ -206,20 +256,29 @@ class MoviePlugin(Plugin):
             char = movie.library.titles[0].simple_title[0]
             char = char if char in ascii_lowercase else '#'
             if char not in chars:
-                chars += char
+                chars += str(char)
 
         #db.close()
-        return chars
+        return ''.join(sorted(chars, key = str.lower))
 
     def listView(self):
 
         params = getParams()
-        status = params.get('status', ['active'])
+        status = splitString(params.get('status', None))
+        release_status = splitString(params.get('release_status', None))
         limit_offset = params.get('limit_offset', None)
         starts_with = params.get('starts_with', None)
         search = params.get('search', None)
+        order = params.get('order', None)
 
-        total_movies, movies = self.list(status = status, limit_offset = limit_offset, starts_with = starts_with, search = search)
+        total_movies, movies = self.list(
+            status = status,
+            release_status = release_status,
+            limit_offset = limit_offset,
+            starts_with = starts_with,
+            search = search,
+            order = order
+        )
 
         return jsonified({
             'success': True,
@@ -231,8 +290,9 @@ class MoviePlugin(Plugin):
     def charView(self):
 
         params = getParams()
-        status = params.get('status', ['active'])
-        chars = self.availableChars(status)
+        status = splitString(params.get('status', None))
+        release_status = splitString(params.get('release_status', None))
+        chars = self.availableChars(status, release_status)
 
         return jsonified({
             'success': True,
@@ -283,7 +343,7 @@ class MoviePlugin(Plugin):
             'movies': movies,
         })
 
-    def add(self, params = {}, force_readd = True, search_after = True, update_library = False):
+    def add(self, params = {}, force_readd = True, search_after = True, update_library = False, status_id = None):
 
         if not params.get('identifier'):
             msg = 'Can\'t add movie without imdb identifier.'
@@ -318,7 +378,7 @@ class MoviePlugin(Plugin):
             m = Movie(
                 library_id = library.get('id'),
                 profile_id = params.get('profile_id', default_profile.get('id')),
-                status_id = status_active.get('id'),
+                status_id = status_id if status_id else status_active.get('id'),
             )
             db.add(m)
             db.commit()
@@ -341,7 +401,7 @@ class MoviePlugin(Plugin):
             added = False
 
         if force_readd:
-            m.status_id = status_active.get('id')
+            m.status_id = status_id if status_id else status_active.get('id')
             do_search = True
 
         db.commit()
@@ -447,7 +507,7 @@ class MoviePlugin(Plugin):
                 total_deleted = 0
                 new_movie_status = None
                 for release in movie.releases:
-                    if delete_from == 'wanted':
+                    if delete_from in ['wanted', 'snatched']:
                         if release.status_id != done_status.get('id'):
                             db.delete(release)
                             total_deleted += 1
diff --git a/couchpotato/core/plugins/movie/static/list.js b/couchpotato/core/plugins/movie/static/list.js
index b61ea7e0..9e76fad3 100644
--- a/couchpotato/core/plugins/movie/static/list.js
+++ b/couchpotato/core/plugins/movie/static/list.js
@@ -5,6 +5,7 @@ var MovieList = new Class({
 	options: {
 		navigation: true,
 		limit: 50,
+		load_more: true,
 		menu: [],
 		add_new: false
 	},
@@ -12,25 +13,32 @@ var MovieList = new Class({
 	movies: [],
 	movies_added: {},
 	letters: {},
-	filter: {
-		'startswith': null,
-		'search': null
-	},
+	filter: null,
 
 	initialize: function(options){
 		var self = this;
 		self.setOptions(options);
 
 		self.offset = 0;
+		self.filter = self.options.filter || {
+			'startswith': null,
+			'search': null
+		}
 
 		self.el = new Element('div.movies').adopt(
+			self.title = self.options.title ? new Element('h2', {
+				'text': self.options.title
+			}) : null,
 			self.movie_list = new Element('div'),
-			self.load_more = new Element('a.load_more', {
+			self.load_more = self.options.load_more ? new Element('a.load_more', {
 				'events': {
 					'click': self.loadMore.bind(self)
 				}
-			})
+			}) : null
 		);
+
+		self.changeView(self.options.view || 'details');
+
 		self.getMovies();
 
 		App.addEvent('movie.added', self.movieAdded.bind(self))
@@ -70,22 +78,14 @@ var MovieList = new Class({
 		if(self.options.navigation)
 			self.createNavigation();
 
-		self.movie_list.addEvents({
-			'mouseenter:relay(.movie)': function(e, el){
-				el.addClass('hover');
-			},
-			'mouseleave:relay(.movie)': function(e, el){
-				el.removeClass('hover');
-			}
-		});
-
-		self.scrollspy = new ScrollSpy({
-			min: function(){
-				var c = self.load_more.getCoordinates()
-				return c.top - window.document.getSize().y - 300
-			},
-			onEnter: self.loadMore.bind(self)
-		});
+		if(self.options.load_more)
+			self.scrollspy = new ScrollSpy({
+				min: function(){
+					var c = self.load_more.getCoordinates()
+					return c.top - window.document.getSize().y - 300
+				},
+				onEnter: self.loadMore.bind(self)
+			});
 
 		self.created = true;
 	},
@@ -96,7 +96,7 @@ var MovieList = new Class({
 		if(!self.created) self.create();
 
 		// do scrollspy
-		if(movies.length < self.options.limit){
+		if(movies.length < self.options.limit && self.scrollspy){
 			self.load_more.hide();
 			self.scrollspy.stop();
 		}
@@ -124,8 +124,8 @@ var MovieList = new Class({
 
 		// Attach proper actions
 		var a = self.options.actions,
-			status = Status.get(movie.status_id);
-		var actions = a[status.identifier.capitalize()] || a.Wanted || {};
+			status = Status.get(movie.status_id),
+			actions = a ? a[status.identifier.capitalize()] || a.Wanted :  {};
 
 		var m = new Movie(self, {
 			'actions': actions,
@@ -216,7 +216,7 @@ var MovieList = new Class({
 		});
 
 		// Actions
-		['mass_edit', 'thumbs', 'list'].each(function(view){
+		['mass_edit', 'details', 'list'].each(function(view){
 			self.navigation_actions.adopt(
 				new Element('li.'+view+(self.current_view == view ? '.active' : '')+'[data-view='+view+']', {
 					'events': {
@@ -401,8 +401,10 @@ var MovieList = new Class({
 		self.calculateSelected()
 		self.navigation_alpha.getElements('.active').removeClass('active')
 		self.offset = 0;
-		self.load_more.show();
-		self.scrollspy.start();
+		if(self.scrollspy){
+			self.load_more.show();
+			self.scrollspy.start();
+		}
 	},
 
 	activateLetter: function(letter){
@@ -418,10 +420,6 @@ var MovieList = new Class({
 	changeView: function(new_view){
 		var self = this;
 
-		self.movies.each(function(movie){
-			movie.changeView(new_view)
-		});
-
 		self.el
 			.removeClass(self.current_view+'_list')
 			.addClass(new_view+'_list')
@@ -468,9 +466,12 @@ var MovieList = new Class({
 	getMovies: function(){
 		var self = this;
 
-		if(self.scrollspy) self.scrollspy.stop();
-		self.load_more.set('text', 'loading...');
-		Api.request('movie.list', {
+		if(self.scrollspy){
+			self.scrollspy.stop();
+			self.load_more.set('text', 'loading...');
+		}
+
+		Api.request(self.options.api_call || 'movie.list', {
 			'data': Object.merge({
 				'status': self.options.status,
 				'limit_offset': self.options.limit + ',' + self.offset
@@ -478,8 +479,10 @@ var MovieList = new Class({
 			'onComplete': function(json){
 				self.store(json.movies);
 				self.addMovies(json.movies, json.total);
-				self.load_more.set('text', 'load more movies');
-				if(self.scrollspy) self.scrollspy.start();
+				if(self.scrollspy) {
+					self.load_more.set('text', 'load more movies');
+					self.scrollspy.start();
+				}
 
 				self.checkIfEmpty()
 			}
@@ -503,6 +506,9 @@ var MovieList = new Class({
 		var self = this;
 
 		var is_empty = self.movies.length == 0 && self.total_movies == 0;
+		
+		if(self.title)
+			self.title[is_empty ? 'hide' : 'show']()
 
 		if(is_empty && self.options.on_empty_element){
 			self.el.grab(self.options.on_empty_element);
diff --git a/couchpotato/core/plugins/movie/static/movie.css b/couchpotato/core/plugins/movie/static/movie.css
index 68e04283..9d67e628 100644
--- a/couchpotato/core/plugins/movie/static/movie.css
+++ b/couchpotato/core/plugins/movie/static/movie.css
@@ -2,6 +2,18 @@
 	padding: 60px 0 20px;
 }
 
+	.movies h2 {
+		margin-bottom: 20px;	
+	}
+	
+	.movies.thumbs_list {
+		padding: 20px 0 20px;
+	}
+	
+	.home .movies {
+		padding-top: 6px;
+	}
+
 	.movies.mass_edit_list {
 		padding-top: 90px;
 	}
@@ -12,33 +24,58 @@
 		margin: 10px 0;
 		overflow: hidden;
 		width: 100%;
+		height: 180px;
 		transition: all 0.2s linear;
 	}
-		.movies .movie.list_view, .movies .movie.mass_edit_view {
+
+		.movies.list_list .movie:not(.details_view),
+		.movies.mass_edit_list .movie {
+			height: 32px;
+		}
+		
+		.movies.thumbs_list .movie {
+			width: 153px;
+			height: 230px;
+			display: inline-block;
+			margin: 0 8px 0 0;
+		}
+			.movies.thumbs_list .movie:nth-child(6n+6) {
+				margin: 0;
+			}
+
+		.movies .movie .mask {
+			position: absolute;
+			top: 0;
+			left: 0;
+			height: 100%;
+			width: 100%;
+		}
+
+		.movies.list_list .movie:not(.details_view),
+		.movies.mass_edit_list .movie {
 			margin: 1px 0;
 			border-radius: 0;
 			background: no-repeat;
 			box-shadow: none;
 			border-bottom: 1px solid rgba(255,255,255,0.05);
 		}
-		.movies .movie.list_view:hover, .movies .movie.mass_edit_view:hover {
-			background: rgba(255,255,255,0.03);
-		}
 
-		.movies .movie_container {
-			overflow: hidden;
+		.movies.list_list .movie:hover:not(.details_view),
+		.movies.mass_edit_list .movie {
+			background: rgba(255,255,255,0.03);
 		}
 
 		.movies .data {
 			padding: 20px;
-			height: 180px;
+			height: 100%;
 			width: 840px;
-			position: relative;
-			float: right;
+			position: absolute;
+			right: 0;
 			border-radius: 0;
-			transition: all 0.2s linear;
+			transition: all .6s cubic-bezier(0.9,0,0.1,1);
 		}
-			.movies .list_view .data, .movies .mass_edit_view .data {
+			.movies.list_list .movie:not(.details_view) .data,
+			.movies.mass_edit_list .movie .data {
 				height: 30px;
 				padding: 3px 0 3px 10px;
 				width: 938px;
@@ -46,79 +83,148 @@
 				border: 0;
 				background: none;
 			}
+			
+			.movies.thumbs_list .data {
+				left: 0;
+				width: 100%;
+				padding: 10px;
+				height: 100%;
+				background: none;
+				transition: none;
+			}
+			
+				.movies.thumbs_list .movie.no_thumbnail .data { background-image: linear-gradient(-30deg, rgba(255, 0, 85, .2) 0,rgba(125, 185, 235, .2) 100%);
+				}
+				.movies.thumbs_list .movie.no_thumbnail:nth-child(2n+6) .data { background-image: linear-gradient(-20deg, rgba(125, 0, 215, .2) 0, rgba(4, 55, 5, .7) 100%); }
+				.movies.thumbs_list .movie.no_thumbnail:nth-child(3n+6) .data { background-image: linear-gradient(-30deg, rgba(155, 0, 85, .2) 0,rgba(25, 185, 235, .7) 100%); }
+				.movies.thumbs_list .movie.no_thumbnail:nth-child(4n+6) .data { background-image: linear-gradient(-30deg, rgba(115, 5, 235, .2) 0, rgba(55, 180, 5, .7) 100%); }
+				.movies.thumbs_list .movie.no_thumbnail:nth-child(5n+6) .data { background-image: linear-gradient(-30deg, rgba(35, 15, 215, .2) 0, rgba(135, 215, 115, .7) 100%); }
+				.movies.thumbs_list .movie.no_thumbnail:nth-child(6n+6) .data { background-image: linear-gradient(-30deg, rgba(35, 15, 215, .2) 0, rgba(135, 15, 115, .7) 100%); }
+				
+				.movies.thumbs_list .movie:hover .data {
+					background: rgba(0,0,0,0.9);
+				}
+
+			.movies .data.hide_right {
+				right: -100%;
+			}
 
 		.movies .movie .check {
 			display: none;
 		}
 
 			.movies.mass_edit_list .movie .check {
-				float: left;
+				position: absolute;
+				left: 0;
+				top: 0;
 				display: block;
 				margin: 7px 0 0 5px;
 			}
 
 		.movies .poster {
-			float: left;
+			position: absolute;
+			left: 0;
 			width: 120px;
 			line-height: 0;
 			overflow: hidden;
-			height: 180px;
+			height: 100%;
 			border-radius: 4px 0 0 4px;
-			transition: all 0.2s linear;
+			transition: all .6s cubic-bezier(0.9,0,0.1,1);
 
 		}
-			.movies .list_view .poster, .movies .mass_edit_view .poster {
+			.movies.list_list .movie:not(.details_view) .poster,
+			.movies.mass_edit_list .poster {
 				width: 20px;
 				height: 30px;
+				border-radius: 1px 0 0 1px;
 			}
 			.movies.mass_edit_list .poster {
 				display: none;
 			}
+			
+			.movies.thumbs_list .poster {
+				width: 100%;
+				height: 100%;
+			}
 
-		.movies .poster img, .options .poster img {
+		.movies .poster img,
+		.options .poster img {
 			width: 101%;
 			height: 101%;
 		}
+		
+			.movies .info {
+				position: relative;
+				height: 100%;
+			}
 
 			.movies .info .title {
-				font-size: 30px;
+				display: inline;
+				position: absolute;
+				font-size: 28px;
 				font-weight: bold;
 				margin-bottom: 10px;
-				float: left;
+				left: 0;
+				top: 0;
 				width: 90%;
 				transition: all 0.2s linear;
 			}
-				.movies .list_view .info .title, .movies .mass_edit_view .info .title {
+				.movies.list_list .movie:not(.details_view) .info .title,
+				.movies.mass_edit_list .info .title {
 					font-size: 16px;
 					font-weight: normal;
 					text-overflow: ellipsis;
 					width: auto;
+					overflow: hidden;
+					
+				}
+				
+				.movies.thumbs_list .movie:not(.no_thumbnail) .info {
+					display: none;
 				}
+					.movies.thumbs_list .movie:hover .info {
+						display: block;
+					}
+				
+					.movies.thumbs_list .info .title {
+						font-size: 21px;
+						text-shadow: 0 0 10px #000;
+						word-wrap: break-word;
+					}
 
 			.movies .info .year {
+				position: absolute;
 				font-size: 30px;
 				margin-bottom: 10px;
-				float: right;
 				color: #bbb;
 				width: 10%;
+				right: 0;
+				top: 0;
 				text-align: right;
 				transition: all 0.2s linear;
 			}
-				.movies .list_view .info .year, .movies .mass_edit_view .info .year {
+				.movies.list_list .movie:not(.details_view) .info .year,
+				.movies.mass_edit_list .info .year {
 					font-size: 16px;
 					width: 6%;
+					right: 10px;
+				}
+				
+				.movies.thumbs_list .info .year {
+					font-size: 23px;
+					margin: 0;
+					bottom: 0;
+					left: 0;
+					top: auto;
+					right: auto;
+					color: #FFF;
+					text-shadow: none;
+					text-shadow: 0 0 6px #000;
 				}
-
-			.movies .info .rating {
-				font-size: 30px;
-				margin-bottom: 10px;
-				color: #444;
-				float: left;
-				width: 5%;
-				padding: 0 0 0 3%;
-			}
 
 			.movies .info .description {
+				position: absolute;
+				top: 30px;
 				clear: both;
 				height: 80px;
 				overflow: hidden;
@@ -126,61 +232,75 @@
 				.movies .data:hover .description {
 					overflow: auto;
 				}
-				.movies .list_view .info .description, .movies .mass_edit_view .info .description {
+				.movies.list_list .movie:not(.details_view) .info .description,
+				.movies.mass_edit_list .info .description,
+				.movies.thumbs_list .info .description {
 					display: none;
 				}
 
 		.movies .data .quality {
+			position: absolute;
+			bottom: 0;
 			display: block;
 			min-height: 20px;
 			vertical-align: mid;
 		}
-
-		.movies .data .quality span {
-			padding: 2px 3px;
-			font-weight: bold;
-			opacity: 0.5;
-			font-size: 10px;
-			height: 16px;
-			line-height: 12px;
-			vertical-align: middle;
-			display: inline-block;
-			text-transform: uppercase;
-			text-shadow: none;
-			font-weight: normal;
-			margin: 0 2px;
-			border-radius: 2px;
-			background-color: rgba(255,255,255,0.1);
-		}
-			.movies .list_view .data .quality, .movies .mass_edit_view .data .quality {
-				text-align: right;
-				float: right;
+		
+			.movies .status_suggest .data .quality,
+			.movies.thumbs_list .data .quality {
+				display: none;
 			}
 
-		.movies .data .quality .available, .movies .data .quality .snatched {
-			opacity: 1;
-			box-shadow: 1px 1px 0 rgba(0,0,0,0.2);
-			cursor: pointer;
-		}
-
-		.movies .data .quality .available { background-color: #578bc3; }
-		.movies .data .quality .snatched { background-color: #369545; }
-		.movies .data .quality .done {
-			background-color: #369545;
-			opacity: 1;
-		}
-		.movies .data .quality .finish {
-			background-image: url('../images/sprite.png');
-			background-repeat:  no-repeat;
-			background-position: 0 2px;
-			padding-left: 14px;
-			background-size: 14px
-		}
+			.movies .data .quality span {
+				padding: 2px 3px;
+				font-weight: bold;
+				opacity: 0.5;
+				font-size: 10px;
+				height: 16px;
+				line-height: 12px;
+				vertical-align: middle;
+				display: inline-block;
+				text-transform: uppercase;
+				text-shadow: none;
+				font-weight: normal;
+				margin: 0 2px;
+				border-radius: 2px;
+				background-color: rgba(255,255,255,0.1);
+			}
+				.movies.list_list .data .quality,
+				.movies.mass_edit_list .data .quality {
+					text-align: right;
+					right: 0;
+					margin-right: 50px;
+					z-index: 2;
+				}
+	
+			.movies .data .quality .available,
+			.movies .data .quality .snatched {
+				opacity: 1;
+				box-shadow: 1px 1px 0 rgba(0,0,0,0.2);
+				cursor: pointer;
+			}
+	
+			.movies .data .quality .available { background-color: #578bc3; }
+			.movies .data .quality .snatched { background-color: #369545; }
+			.movies .data .quality .done {
+				background-color: #369545;
+				opacity: 1;
+			}
+			.movies .data .quality .finish {
+				background-image: url('../images/sprite.png');
+				background-repeat:  no-repeat;
+				background-position: 0 2px;
+				padding-left: 14px;
+				background-size: 14px
+			}
 
 		.movies .data .actions {
+			position: absolute;
+			bottom: 20px;
+			right: 20px;
 			line-height: 0;
-			clear: both;
-			float: right;
 			margin-top: -25px;
 		}
 			.movies .data:hover .action { opacity: 0.6; }
@@ -199,10 +319,14 @@
 				opacity: 0;
 			}
 
-		.movies .list_view .data:hover .actions, .movies .mass_edit_view .data:hover .actions {
-			margin: -34px 2px 0 0;
+		.movies.list_list .movie:not(.details_view) .data:hover .actions,
+		.movies.mass_edit_list .data:hover .actions {
+			margin: 0;
 			background: #4e5969;
-			position: relative;
+			top: 2px;
+			bottom: 2px;
+			right: 5px;
+			z-index: 3;
 		}
 
 		.movies .delete_container {
@@ -336,11 +460,11 @@
 						padding: 3px 10px;
 						background: #4e5969;
 						border-radius: 0 0 2px 2px;
-						transition: all .6s cubic-bezier(0.9,0,0.1,1) .2s;
-					}
-					.movies .movie .hide_trailer.hide {
-						top: -30px;
+						transition: all .2s cubic-bezier(0.9,0,0.1,1) .2s;
 					}
+						.movies .movie .hide_trailer.hide {
+							top: -30px;
+						}
 
 				.movies .movie .try_container {
 					padding: 5px 10px;
@@ -410,7 +534,8 @@
 		text-align: center;
 	}
 
-	.movies .alph_nav .numbers li, .movies .alph_nav .actions li {
+	.movies .alph_nav .numbers li, 
+	.movies .alph_nav .actions li {
 		display: inline-block;
 		vertical-align: top;
 		width: 20px;
@@ -473,7 +598,7 @@
 				background-position: 3px -95px;
 			}
 
-			.movies .alph_nav .actions li.thumbs span {
+			.movies .alph_nav .actions li.details span {
 				background-position: 3px -74px;
 			}
 
diff --git a/couchpotato/core/plugins/movie/static/movie.js b/couchpotato/core/plugins/movie/static/movie.js
index ff2cd12c..283bb414 100644
--- a/couchpotato/core/plugins/movie/static/movie.js
+++ b/couchpotato/core/plugins/movie/static/movie.js
@@ -8,7 +8,7 @@ var Movie = new Class({
 		var self = this;
 
 		self.data = data;
-		self.view = options.view || 'thumbs';
+		self.view = options.view || 'details';
 		self.list = list;
 
 		self.el = new Element('div.movie.inlay');
@@ -72,7 +72,6 @@ var Movie = new Class({
 		else if(!self.spinner) {
 			self.createMask();
 			self.spinner = createSpinner(self.mask);
-			self.positionMask();
 			self.mask.fade('in');
 		}
 	},
@@ -84,7 +83,6 @@ var Movie = new Class({
 				'z-index': '1'
 			}
 		}).inject(self.el, 'top').fade('hide');
-		self.positionMask();
 	},
 
 	positionMask: function(){
@@ -103,7 +101,7 @@ var Movie = new Class({
 		var self = this;
 
 		self.data = notification.data;
-		self.container.destroy();
+		self.el.empty();
 
 		self.profile = Quality.getProfile(self.data.profile_id) || {};
 		self.create();
@@ -114,52 +112,50 @@ var Movie = new Class({
 	create: function(){
 		var self = this;
 
+		var s = Status.get(self.get('status_id'));
+		self.el.addClass('status_'+s.identifier);
+
 		self.el.adopt(
-			self.container = new Element('div.movie_container').adopt(
-				self.select_checkbox = new Element('input[type=checkbox].inlay', {
-					'events': {
-						'change': function(){
-							self.fireEvent('select')
-						}
+			self.select_checkbox = new Element('input[type=checkbox].inlay', {
+				'events': {
+					'change': function(){
+						self.fireEvent('select')
 					}
-				}),
-				self.thumbnail = File.Select.single('poster', self.data.library.files),
-				self.data_container = new Element('div.data.inlay.light', {
-					'tween': {
-						duration: 400,
-						transition: 'quint:in:out',
-						onComplete: self.fireEvent.bind(self, 'slideEnd')
-					}
-				}).adopt(
-					self.info_container = new Element('div.info').adopt(
-						self.title = new Element('div.title', {
-							'text': self.getTitle() || 'n/a'
-						}),
-						self.year = new Element('div.year', {
-							'text': self.data.library.year || 'n/a'
-						}),
-						self.rating = new Element('div.rating.icon', {
-							'text': self.data.library.rating
-						}),
-						self.description = new Element('div.description', {
-							'text': self.data.library.plot
-						}),
-						self.quality = new Element('div.quality', {
-							'events': {
-								'click': function(e){
-									var releases = self.el.getElement('.actions .releases');
-										if(releases)
-											releases.fireEvent('click', [e])
-								}
+				}
+			}),
+			self.thumbnail = File.Select.single('poster', self.data.library.files),
+			self.data_container = new Element('div.data.inlay.light').adopt(
+				self.info_container = new Element('div.info').adopt(
+					self.title = new Element('div.title', {
+						'text': self.getTitle() || 'n/a'
+					}),
+					self.year = new Element('div.year', {
+						'text': self.data.library.year || 'n/a'
+					}),
+					self.rating = new Element('div.rating.icon', {
+						'text': self.data.library.rating
+					}),
+					self.description = new Element('div.description', {
+						'text': self.data.library.plot
+					}),
+					self.quality = new Element('div.quality', {
+						'events': {
+							'click': function(e){
+								var releases = self.el.getElement('.actions .releases');
+									if(releases)
+										releases.fireEvent('click', [e])
 							}
-						})
-					),
-					self.actions = new Element('div.actions')
-				)
+						}
+					})
+				),
+				self.actions = new Element('div.actions')
 			)
 		);
 
-		self.changeView(self.view);
+		if(self.thumbnail.empty)
+			self.el.addClass('no_thumbnail');
+
+		//self.changeView(self.view);
 		self.select_checkbox_class = new Form.Check(self.select_checkbox);
 
 		// Add profile
@@ -174,7 +170,7 @@ var Movie = new Class({
 
 			});
 
-		// Add done releases
+		// Add releases
 		self.data.releases.each(function(release){
 
 			var q = self.quality.getElement('.q_id'+ release.quality_id),
@@ -241,23 +237,23 @@ var Movie = new Class({
 
 		if(direction == 'in'){
 			self.temp_view = self.view;
-			self.changeView('thumbs')
+			self.changeView('details')
 
 			self.el.addEvent('outerClick', function(){
-				self.changeView(self.temp_view)
+				self.removeView()
 				self.slide('out')
 			})
 			el.show();
-			self.data_container.tween('right', 0, -840);
+			self.data_container.addClass('hide_right');
 		}
 		else {
 			self.el.removeEvents('outerClick')
 
-			self.addEvent('slideEnd:once', function(){
+			setTimeout(function(){
 				self.el.getElements('> :not(.data):not(.poster):not(.movie_container)').hide();
-			});
+			}, 600);
 
-			self.data_container.tween('right', -840, 0);
+			self.data_container.removeClass('hide_right');
 		}
 	},
 
@@ -271,6 +267,12 @@ var Movie = new Class({
 		self.view = new_view;
 	},
 
+	removeView: function(){
+		var self = this;
+
+		self.el.removeClass(self.view+'_view')
+	},
+
 	get: function(attr){
 		return this.data[attr] || this.data.library[attr]
 	},
@@ -320,7 +322,7 @@ var MovieAction = new Class({
 				'z-index': '1'
 			}
 		}).inject(self.movie, 'top').fade('hide');
-		self.positionMask();
+		//self.positionMask();
 	},
 
 	positionMask: function(){
@@ -379,20 +381,27 @@ var ReleaseAction = new Class({
 			}
 		});
 
-		var buttons_done = false;
+		if(self.movie.data.releases.length == 0){
+			self.el.hide()
+		}
+		else {
+
+			var buttons_done = false;
 
-		self.movie.data.releases.sortBy('-info.score').each(function(release){
-			if(buttons_done) return;
+			self.movie.data.releases.sortBy('-info.score').each(function(release){
+				if(buttons_done) return;
 
-			var status = Status.get(release.status_id);
+				var status = Status.get(release.status_id);
 
-			if((self.next_release && (status.identifier == 'ignored' || status.identifier == 'failed')) || (!self.next_release && status.identifier == 'available')){
-				self.hide_on_click = false;
-				self.show();
-				buttons_done = true;
-			}
+				if((self.next_release && (status.identifier == 'ignored' || status.identifier == 'failed')) || (!self.next_release && status.identifier == 'available')){
+					self.hide_on_click = false;
+					self.show();
+					buttons_done = true;
+				}
 
-		});
+			});
+
+		}
 
 	},
 
@@ -603,7 +612,7 @@ var TrailerAction = new Class({
 		self.player_container = new Element('div[id='+id+']');
 		self.container = new Element('div.hide.trailer_container')
 			.adopt(self.player_container)
-			.inject(self.movie.container, 'top');
+			.inject($(self.movie), 'top');
 
 		self.container.setStyle('height', 0);
 		self.container.removeClass('hide');
@@ -615,10 +624,8 @@ var TrailerAction = new Class({
 			}
 		}).inject(self.movie);
 
-		setTimeout(function(){
-			$(self.movie).setStyle('max-height', height);
-			self.container.setStyle('height', height);
-		}, 100)
+		self.container.setStyle('height', height);
+		$(self.movie).setStyle('height', height);
 
 		new Request.JSONP({
 			'url': url,
@@ -665,6 +672,7 @@ var TrailerAction = new Class({
 		self.player.stopVideo();
 		self.container.addClass('hide');
 		self.close_button.addClass('hide');
+		$(self.movie).setStyle('height', null);
 
 		setTimeout(function(){
 			self.container.destroy()
diff --git a/couchpotato/core/plugins/movie/static/search.css b/couchpotato/core/plugins/movie/static/search.css
index af942295..391e3476 100644
--- a/couchpotato/core/plugins/movie/static/search.css
+++ b/couchpotato/core/plugins/movie/static/search.css
@@ -191,6 +191,8 @@
 
 				.movie_result .info h2 {
 					margin: 0;
+					font-size: 17px;
+					line-height: 20px;
 				}
 
 				.movie_result .info h2 span {
diff --git a/couchpotato/core/plugins/searcher/main.py b/couchpotato/core/plugins/searcher/main.py
index 8c1929af..c5ed1380 100644
--- a/couchpotato/core/plugins/searcher/main.py
+++ b/couchpotato/core/plugins/searcher/main.py
@@ -30,6 +30,7 @@ class Searcher(Plugin):
         addEvent('searcher.correct_movie', self.correctMovie)
         addEvent('searcher.download', self.download)
         addEvent('searcher.try_next_release', self.tryNextRelease)
+        addEvent('searcher.could_be_released', self.couldBeReleased)
 
         addApiView('searcher.try_next', self.tryNextReleaseView, docs = {
             'desc': 'Marks the snatched results as ignored and try the next best release',
@@ -156,7 +157,7 @@ class Searcher(Plugin):
 
         ret = False
         for quality_type in movie['profile']['types']:
-            if not self.couldBeReleased(quality_type['quality']['identifier'], release_dates, pre_releases):
+            if not self.couldBeReleased(quality_type['quality']['identifier'] in pre_releases, release_dates):
                 log.info('Too early to search for %s, %s', (quality_type['quality']['identifier'], default_title))
                 continue
 
@@ -526,7 +527,7 @@ class Searcher(Plugin):
 
         return False
 
-    def couldBeReleased(self, wanted_quality, dates, pre_releases):
+    def couldBeReleased(self, is_pre_release, dates):
 
         now = int(time.time())
 
@@ -538,7 +539,7 @@ class Searcher(Plugin):
             if dates.get('theater', 0) < 0 or dates.get('dvd', 0) < 0:
                 return True
 
-            if wanted_quality in pre_releases:
+            if is_pre_release:
                 # Prerelease 1 week before theaters
                 if dates.get('theater') - 604800 < now:
                     return True
diff --git a/couchpotato/static/scripts/couchpotato.js b/couchpotato/static/scripts/couchpotato.js
index 8f4e665f..d2e8fa00 100644
--- a/couchpotato/static/scripts/couchpotato.js
+++ b/couchpotato/static/scripts/couchpotato.js
@@ -3,7 +3,7 @@ var CouchPotato = new Class({
 	Implements: [Events, Options],
 
 	defaults: {
-		page: 'wanted',
+		page: 'home',
 		action: 'index',
 		params: {}
 	},
@@ -135,7 +135,7 @@ var CouchPotato = new Class({
 			self.current_page.hide()
 
 		try {
-			var page = self.pages[page_name] || self.pages.Wanted;
+			var page = self.pages[page_name] || self.pages.Home;
 			page.open(action, params, current_url);
 			page.show();
 		}
@@ -342,7 +342,14 @@ var Route = new Class({
 	parse: function(){
 		var self = this;
 
-		var path = History.getPath().replace(Api.getOption('url'), '/').replace(App.getOption('base_url'), '/')
+		var rep = function(pa){
+			return pa.replace(Api.getOption('url'), '/').replace(App.getOption('base_url'), '/')
+		}
+
+		var path = rep(History.getPath())
+		if(path == '/' && location.hash){
+			path = rep(location.hash.replace('#', '/'))
+		}
 		self.current = path.replace(/^\/+|\/+$/g, '')
 		var url = self.current.split('/')
 
diff --git a/couchpotato/static/scripts/page/home.js b/couchpotato/static/scripts/page/home.js
new file mode 100644
index 00000000..caf4d646
--- /dev/null
+++ b/couchpotato/static/scripts/page/home.js
@@ -0,0 +1,91 @@
+Page.Home = new Class({
+
+	Extends: PageBase,
+
+	name: 'home',
+	title: 'Manage new stuff for things and such',
+
+	indexAction: function(param){
+		var self = this;
+
+		if(self.soon_list)
+			return
+
+		// Snatched
+		self.available_list = new MovieList({
+			'navigation': false,
+			'identifier': 'snatched',
+			'load_more': false,
+			'view': 'list',
+			'actions': MovieActions,
+			'title': 'Snatched & Available',
+			'filter': {
+				'release_status': 'snatched,available'
+			}
+		});
+
+		// Downloaded
+		// self.downloaded_list = new MovieList({
+			// 'navigation': false,
+			// 'identifier': 'downloaded',
+			// 'load_more': false,
+			// 'view': 'titles',
+			// 'filter': {
+				// 'release_status': 'done',
+				// 'order': 'release_order'
+			// }
+		// });
+		// self.el.adopt(
+			// new Element('h2', {
+				// 'text': 'Just downloaded'
+			// }),
+			// $(self.downloaded_list)
+		// );
+
+		// Comming Soon
+		self.soon_list = new MovieList({
+			'navigation': false,
+			'identifier': 'soon',
+			'limit': 24,
+			'title': 'Soon',
+			'filter': {
+				'random': true
+			},
+			'load_more': false,
+			'view': 'thumbs',
+			'api_call': 'dashboard.soon'
+		});
+
+		self.el.adopt(
+			$(self.available_list),
+			$(self.soon_list)
+		);
+
+		// Suggest
+		// self.suggestion_list = new MovieList({
+			// 'navigation': false,
+			// 'identifier': 'suggestions',
+			// 'limit': 6,
+			// 'load_more': false,
+			// 'view': 'thumbs',
+			// 'api_call': 'suggestion.suggest'
+		// });
+		// self.el.adopt(
+			// new Element('h2', {
+				// 'text': 'You might like'
+			// }),
+			// $(self.suggestion_list)
+		// );
+
+		// Recent
+			// Snatched
+			// Renamed
+			// Added
+
+		// Free space
+
+		// Shortcuts
+
+	}
+
+})
\ No newline at end of file
diff --git a/couchpotato/static/scripts/page/manage.js b/couchpotato/static/scripts/page/manage.js
index 0e44e767..ec293f86 100644
--- a/couchpotato/static/scripts/page/manage.js
+++ b/couchpotato/static/scripts/page/manage.js
@@ -27,7 +27,9 @@ Page.Manage = new Class({
 
 			self.list = new MovieList({
 				'identifier': 'manage',
-				'status': 'done',
+				'filter': {
+					'release_status': 'done'
+				},
 				'actions': MovieActions,
 				'menu': [self.refresh_button, self.refresh_quick],
 				'on_empty_element': new Element('div.empty_manage').adopt(
diff --git a/couchpotato/static/style/main.css b/couchpotato/static/style/main.css
index 97ca1837..ff292226 100644
--- a/couchpotato/static/style/main.css
+++ b/couchpotato/static/style/main.css
@@ -80,6 +80,12 @@ a:hover { color: #f3f3f3; }
 	padding: 80px 0 10px;
 }
 
+h2 {
+	font-size: 30px;
+	padding: 0;
+	margin: 20px 0 0 0;
+}
+
 .footer {
 	text-align:center;
 	padding: 50px 0 0 0;
-- 
GitLab