mirror of
https://github.com/devfake/flox.git
synced 2024-11-14 22:22:39 +01:00
Implement watchlist feature (#84)
* implement watchlist feature * update production files * fix migration error * change current route to now-playing
This commit is contained in:
parent
6ee5bfefcf
commit
1a224a50ed
@ -44,6 +44,15 @@
|
||||
return $this->itemService->create(Input::get('item'));
|
||||
}
|
||||
|
||||
public function watchlist()
|
||||
{
|
||||
$item = $this->add();
|
||||
|
||||
$item->update(['watchlist' => true]);
|
||||
|
||||
return $item;
|
||||
}
|
||||
|
||||
public function remove($itemId)
|
||||
{
|
||||
return $this->itemService->remove($itemId);
|
||||
|
@ -57,6 +57,7 @@
|
||||
'date' => $settings->show_date,
|
||||
'spoiler' => $settings->episode_spoiler_protection,
|
||||
'version' => $this->version,
|
||||
'watchlist' => $settings->show_watchlist_everywhere,
|
||||
];
|
||||
}
|
||||
|
||||
@ -79,6 +80,7 @@
|
||||
'show_genre' => Input::get('genre'),
|
||||
'show_date' => Input::get('date'),
|
||||
'episode_spoiler_protection' => Input::get('spoiler'),
|
||||
'show_watchlist_everywhere' => Input::get('watchlist'),
|
||||
]);
|
||||
}
|
||||
}
|
@ -29,9 +29,9 @@
|
||||
return $this->tmdb->trending();
|
||||
}
|
||||
|
||||
public function current()
|
||||
public function nowPlaying()
|
||||
{
|
||||
return $this->tmdb->current();
|
||||
return $this->tmdb->nowPlaying();
|
||||
}
|
||||
|
||||
public function upcoming()
|
||||
|
@ -31,6 +31,7 @@
|
||||
'backdrop',
|
||||
'youtube_key',
|
||||
'slug',
|
||||
'watchlist',
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -3,11 +3,11 @@
|
||||
namespace App\Services\Models;
|
||||
|
||||
use App\Item as Model;
|
||||
use App\Item;
|
||||
use App\Services\IMDB;
|
||||
use App\Services\Storage;
|
||||
use App\Services\TMDB;
|
||||
use GuzzleHttp\Client;
|
||||
use App\Setting;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class ItemService {
|
||||
@ -18,14 +18,16 @@
|
||||
private $alternativeTitleService;
|
||||
private $episodeService;
|
||||
private $imdb;
|
||||
private $setting;
|
||||
|
||||
/**
|
||||
* @param Model $model
|
||||
* @param TMDB $tmdb
|
||||
* @param Storage $storage
|
||||
* @param Model $model
|
||||
* @param TMDB $tmdb
|
||||
* @param Storage $storage
|
||||
* @param AlternativeTitleService $alternativeTitleService
|
||||
* @param EpisodeService $episodeService
|
||||
* @param IMDB $imdb
|
||||
* @param EpisodeService $episodeService
|
||||
* @param IMDB $imdb
|
||||
* @param Setting $setting
|
||||
*/
|
||||
public function __construct(
|
||||
Model $model,
|
||||
@ -33,7 +35,8 @@
|
||||
Storage $storage,
|
||||
AlternativeTitleService $alternativeTitleService,
|
||||
EpisodeService $episodeService,
|
||||
IMDB $imdb
|
||||
IMDB $imdb,
|
||||
Setting $setting
|
||||
){
|
||||
$this->model = $model;
|
||||
$this->tmdb = $tmdb;
|
||||
@ -41,6 +44,7 @@
|
||||
$this->alternativeTitleService = $alternativeTitleService;
|
||||
$this->episodeService = $episodeService;
|
||||
$this->imdb = $imdb;
|
||||
$this->setting = $setting;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -170,7 +174,7 @@
|
||||
return $this->imdb->parseRating($imdbId);
|
||||
}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Otherwise we already have the rating saved.
|
||||
@ -210,7 +214,7 @@
|
||||
/**
|
||||
* @param $data
|
||||
* @param $mediaType
|
||||
* @return Item
|
||||
* @return Model
|
||||
*/
|
||||
public function createEmpty($data, $mediaType)
|
||||
{
|
||||
@ -259,19 +263,23 @@
|
||||
*/
|
||||
public function getWithPagination($type, $orderBy)
|
||||
{
|
||||
$orderType = $orderBy == 'rating' ? 'asc' : 'desc';
|
||||
$items = $this->model->orderBy($orderBy, 'asc')->with('latestEpisode')->withCount('episodesWithSrc');
|
||||
|
||||
$items = $this->model->orderBy($orderBy, $orderType)->with('latestEpisode')->withCount('episodesWithSrc');
|
||||
if($type == 'watchlist') {
|
||||
$items->where('watchlist', true);
|
||||
} elseif( ! $this->setting->first()->show_watchlist_everywhere) {
|
||||
$items->where('watchlist', false);
|
||||
}
|
||||
|
||||
if($type == 'tv' || $type == 'movie') {
|
||||
$items = $items->where('media_type', $type);
|
||||
$items->where('media_type', $type);
|
||||
}
|
||||
|
||||
return $items->simplePaginate(config('app.LOADING_ITEMS'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update rating for a movie.
|
||||
* Update rating.
|
||||
*
|
||||
* @param $itemId
|
||||
* @param $rating
|
||||
@ -292,6 +300,7 @@
|
||||
|
||||
$item->update([
|
||||
'rating' => $rating,
|
||||
'watchlist' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -121,7 +121,7 @@
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function current()
|
||||
public function nowPlaying()
|
||||
{
|
||||
$cache = Cache::remember('current', $this->untilEndOfDay(), function() {
|
||||
$region = getRegion($this->translation);
|
||||
|
@ -16,5 +16,6 @@
|
||||
'show_genre',
|
||||
'episode_spoiler_protection',
|
||||
'last_fetch_to_file_parser',
|
||||
'show_watchlist_everywhere',
|
||||
];
|
||||
}
|
||||
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddWatchlistFieldToItemsTabe extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::table('items', function (Blueprint $table) {
|
||||
$table->boolean('watchlist')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
public function down() {}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddShowWatchlistEverywhereField extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->boolean('show_watchlist_everywhere')->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
public function down() {}
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
Route::get('/suggestions/{tmdbID}/{mediaType}', 'TMDBController@suggestions');
|
||||
Route::get('/trending', 'TMDBController@trending');
|
||||
Route::get('/upcoming', 'TMDBController@upcoming');
|
||||
Route::get('/current', 'TMDBController@current');
|
||||
Route::get('/now-playing', 'TMDBController@nowPlaying');
|
||||
|
||||
Route::patch('/refresh-all', 'ItemController@refreshAll');
|
||||
Route::get('/settings', 'SettingController@settings');
|
||||
@ -25,6 +25,7 @@
|
||||
Route::patch('/settings', 'SettingController@updateSettings');
|
||||
|
||||
Route::post('/add', 'ItemController@add');
|
||||
Route::post('/watchlist', 'ItemController@watchlist');
|
||||
Route::patch('/update-alternative-titles/{tmdbId?}', 'ItemController@updateAlternativeTitles');
|
||||
Route::patch('/update-genre', 'ItemController@updateGenre');
|
||||
Route::patch('/toggle-episode/{id}', 'ItemController@toggleEpisode');
|
||||
|
@ -28,6 +28,7 @@
|
||||
'genre' => 1,
|
||||
'date' => 0,
|
||||
'spoiler' => 0,
|
||||
'watchlist' => 1,
|
||||
]);
|
||||
|
||||
$setting2 = Setting::first();
|
||||
@ -35,8 +36,10 @@
|
||||
$this->assertEquals(0, $setting1->show_genre);
|
||||
$this->assertEquals(1, $setting1->show_date);
|
||||
$this->assertEquals(1, $setting1->episode_spoiler_protection);
|
||||
$this->assertEquals(0, $setting1->show_watchlist_everywhere);
|
||||
$this->assertEquals(1, $setting2->show_genre);
|
||||
$this->assertEquals(0, $setting2->show_date);
|
||||
$this->assertEquals(0, $setting2->episode_spoiler_protection);
|
||||
$this->assertEquals(1, $setting2->show_watchlist_everywhere );
|
||||
}
|
||||
}
|
||||
|
@ -67,9 +67,9 @@
|
||||
case 'home':
|
||||
return this.setPageTitle();
|
||||
case 'tv':
|
||||
return this.setPageTitle(this.lang('tv'));
|
||||
case 'movie':
|
||||
return this.setPageTitle(this.lang('movies'));
|
||||
case 'watchlist':
|
||||
return this.setPageTitle(this.lang(name));
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -2,10 +2,12 @@
|
||||
<transition mode="out-in" name="fade">
|
||||
<div class="item-wrap">
|
||||
<div class="item-image-wrap no-select">
|
||||
<rating :item="localItem" :set-item="setItem"></rating>
|
||||
<rating :rated="rated" :item="localItem" :set-item="setItem"></rating>
|
||||
|
||||
<router-link v-if="localItem.tmdb_id" :to="suggestionsUri(localItem)" class="recommend-item">{{ lang('suggestions') }}</router-link>
|
||||
<span v-if="auth && localItem.rating == null" class="add-to-watchlist" @click="addToWatchlist()">{{ lang('add to watchlist') }}</span>
|
||||
<span v-if="localItem.watchlist" class="is-on-watchlist"><i class="icon-watchlist"></i></span>
|
||||
<span v-if="auth && localItem.rating == null && ! rated" class="add-to-watchlist" @click="addToWatchlist(localItem)">{{ lang('add to watchlist') }}</span>
|
||||
<span v-if="auth && localItem.watchlist && ! rated" class="remove-from-watchlist" @click="removeItem()">{{ lang('remove from watchlist') }}</span>
|
||||
<span v-if="auth && ! localItem.tmdb_id" class="edit-item" @click="editItem()">Edit</span>
|
||||
|
||||
<router-link :to="{ name: `subpage-${localItem.media_type}`, params: { tmdbId: localItem.tmdb_id, slug: localItem.slug }}">
|
||||
@ -48,7 +50,8 @@
|
||||
localItem: this.item,
|
||||
latestEpisode: this.item.latest_episode,
|
||||
prevRating: null,
|
||||
auth: config.auth
|
||||
auth: config.auth,
|
||||
rated: false
|
||||
}
|
||||
},
|
||||
|
||||
@ -73,7 +76,7 @@
|
||||
const path = this.$route.path;
|
||||
const released = new Date(this.localItem.released * 1000);
|
||||
|
||||
if(path === '/upcoming' || path === '/current') {
|
||||
if(path === '/upcoming' || path === '/now-playing') {
|
||||
return this.formatLocaleDate(released);
|
||||
}
|
||||
|
||||
@ -82,15 +85,24 @@
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapMutations([ 'OPEN_MODAL' ]),
|
||||
...mapMutations([ 'OPEN_MODAL', 'SET_RATED' ]),
|
||||
...mapActions([ 'fetchEpisodes' ]),
|
||||
|
||||
setItem(item) {
|
||||
this.localItem = item;
|
||||
},
|
||||
|
||||
addToWatchlist() {
|
||||
removeItem() {
|
||||
this.rated = true;
|
||||
|
||||
http.delete(`${config.api}/remove/${this.localItem.id}`).then(response => {
|
||||
this.rated = false;
|
||||
this.localItem.rating = null;
|
||||
this.localItem.watchlist = null;
|
||||
}, error => {
|
||||
alert(error);
|
||||
this.rated = false;
|
||||
});
|
||||
},
|
||||
|
||||
editItem() {
|
||||
|
@ -3,10 +3,10 @@
|
||||
<div class="wrap-content">
|
||||
|
||||
<div class="navigation-tab no-select">
|
||||
<span :class="{active: activeTab == 'misc'}" @click="changeActiveTab('misc')">{{ lang('tab misc') }}</span>
|
||||
<span :class="{active: activeTab == 'user'}" @click="changeActiveTab('user')">{{ lang('tab user') }}</span>
|
||||
<span :class="{active: activeTab == 'options'}" @click="changeActiveTab('options')">{{ lang('tab options') }}</span>
|
||||
<span :class="{active: activeTab == 'backup'}" @click="changeActiveTab('backup')">{{ lang('tab backup') }}</span>
|
||||
<span :class="{active: activeTab == 'misc'}" @click="changeActiveTab('misc')">{{ lang('tab misc') }}</span>
|
||||
</div>
|
||||
|
||||
<span class="loader fullsize-loader" v-if="loading"><i></i></span>
|
||||
@ -42,7 +42,7 @@
|
||||
|
||||
data() {
|
||||
return {
|
||||
activeTab: 'user'
|
||||
activeTab: 'misc'
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
<span class="update-check" v-if="isUpdate">
|
||||
<a href="https://github.com/devfake/flox/releases" target="_blank" class="new-update">{{ lang('new update') }}</a>
|
||||
</span>
|
||||
<span class="update-check">{{ lang('feedback') }} <a href="https://github.com/devfake/flox/issues" target="_blank">GitHub</a></span>
|
||||
</div>
|
||||
|
||||
<div class="misc-btn-wrap">
|
||||
|
@ -1,15 +1,18 @@
|
||||
<template>
|
||||
|
||||
<div class="settings-box no-select" v-if=" ! loading">
|
||||
<div class="checkbox">
|
||||
<div class="setting-box">
|
||||
<input type="checkbox" value="genre" v-model="genre" id="genre" @change="updateOptions"><label for="genre">{{ lang('display genre') }}</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<div class="setting-box">
|
||||
<input type="checkbox" value="date" v-model="date" id="date" @change="updateOptions"><label for="date">{{ lang('display date') }}</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<div class="setting-box">
|
||||
<input type="checkbox" value="spoiler" v-model="spoiler" id="spoiler" @change="updateOptions"><label for="spoiler">{{ lang('spoiler') }}</label>
|
||||
</div>
|
||||
<div class="setting-box">
|
||||
<input type="checkbox" value="watchlist" v-model="watchlist" id="watchlist" @change="updateOptions"><label for="watchlist">{{ lang('show watchlist') }}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
@ -19,16 +22,12 @@
|
||||
import MiscHelper from '../../../helpers/misc';
|
||||
|
||||
import http from 'axios';
|
||||
import debounce from 'debounce';
|
||||
|
||||
const debounceMilliseconds = 700;
|
||||
|
||||
export default {
|
||||
mixins: [MiscHelper],
|
||||
|
||||
created() {
|
||||
this.fetchOptions();
|
||||
this.updateOptions = debounce(this.updateOptions, debounceMilliseconds);
|
||||
},
|
||||
|
||||
data() {
|
||||
@ -36,6 +35,7 @@
|
||||
genre: null,
|
||||
date: null,
|
||||
spoiler: null,
|
||||
watchlist: null
|
||||
}
|
||||
},
|
||||
|
||||
@ -57,17 +57,23 @@
|
||||
this.genre = data.genre;
|
||||
this.date = data.date;
|
||||
this.spoiler = data.spoiler;
|
||||
this.watchlist = data.watchlist;
|
||||
});
|
||||
},
|
||||
|
||||
updateOptions() {
|
||||
this.SET_LOADING(true);
|
||||
|
||||
const date = this.date;
|
||||
const genre = this.genre;
|
||||
const spoiler = this.spoiler;
|
||||
const watchlist = this.watchlist;
|
||||
|
||||
http.patch(`${config.api}/settings`, {date, genre, spoiler}).catch(() => {
|
||||
alert('Error');
|
||||
});
|
||||
http.patch(`${config.api}/settings`, {date, genre, spoiler, watchlist}).then(response => {
|
||||
this.SET_LOADING(false);
|
||||
}, error => {
|
||||
alert(error.message);
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
<div class="big-teaser-data-wrap">
|
||||
|
||||
<div class="subpage-poster-wrap-mobile">
|
||||
<rating :item="item" :set-item="setItem"></rating>
|
||||
<rating :rated="rated" :item="item" :set-item="setItem"></rating>
|
||||
<img class="base" :src="noImage" width="120" height="180">
|
||||
<img class="real" :src="posterImage" width="120" height="180">
|
||||
</div>
|
||||
@ -23,7 +23,8 @@
|
||||
</div>
|
||||
<div class="big-teaser-buttons no-select" :class="{'without-watchlist': item.rating != null || ! auth}">
|
||||
<span @click="openTrailer()" v-if="item.youtube_key" class="button-trailer"><i class="icon-trailer"></i> {{ lang('watch trailer') }}</span>
|
||||
<span v-if="item.rating == null && auth" class="button-watchlist"><i class="icon-watchlist"></i> {{ lang('add to watchlist') }}</span>
|
||||
<span class="button-watchlist" v-if="item.rating == null && auth && ! rated" @click="addToWatchlist(item)"><i class="icon-watchlist"></i> {{ lang('add to watchlist') }}</span>
|
||||
<span class="button-watchlist" v-if="item.watchlist && auth && ! rated" @click="removeItem()"><i class="icon-watchlist-remove"></i> {{ lang('remove from watchlist') }}</span>
|
||||
<a :href="`https://www.themoviedb.org/${item.media_type}/${item.tmdb_id}`" target="_blank" class="button-tmdb-rating">
|
||||
<i v-if="item.tmdb_rating && item.tmdb_rating != 0"><b>{{ item.tmdb_rating }}</b> TMDb</i>
|
||||
<i v-else>{{ lang('no tmdb rating') }}</i>
|
||||
@ -48,7 +49,7 @@
|
||||
|
||||
<div class="subpage-sidebar">
|
||||
<div class="subpage-poster-wrap">
|
||||
<rating :item="item" :set-item="setItem"></rating>
|
||||
<rating :rated="rated" :item="item" :set-item="setItem"></rating>
|
||||
<img class="base" :src="noImage" width="272" height="408">
|
||||
<img class="real" :src="posterImage" width="272" height="408">
|
||||
|
||||
@ -62,7 +63,7 @@
|
||||
<!-- todo: move to own component -->
|
||||
<div class="subpage-sidebar-buttons no-select" v-if="item.rating != null && auth">
|
||||
<span class="refresh-infos" @click="refreshInfos()">{{ lang('refresh infos') }}</span>
|
||||
<span class="remove-item" @click="removeItem()">{{ lang('delete item') }}</span>
|
||||
<span class="remove-item" @click="removeItem()" v-if=" ! item.watchlist">{{ lang('delete item') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -102,7 +103,8 @@
|
||||
item: {},
|
||||
latestEpisode: null,
|
||||
loadingImdb: false,
|
||||
auth: config.auth
|
||||
auth: config.auth,
|
||||
rated: false
|
||||
}
|
||||
},
|
||||
|
||||
@ -152,7 +154,7 @@
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapMutations([ 'SET_LOADING', 'SET_ITEM_LOADED_SUBPAGE', 'OPEN_MODAL', 'CLOSE_MODAL' ]),
|
||||
...mapMutations([ 'SET_LOADING', 'SET_ITEM_LOADED_SUBPAGE', 'OPEN_MODAL', 'CLOSE_MODAL', 'SET_RATED' ]),
|
||||
...mapActions([ 'setPageTitle', 'fetchEpisodes' ]),
|
||||
|
||||
openTrailer() {
|
||||
@ -218,15 +220,16 @@
|
||||
},
|
||||
|
||||
removeItem() {
|
||||
const confirm = window.confirm(this.lang('confirm delete'));
|
||||
this.rated = true;
|
||||
|
||||
if(confirm) {
|
||||
http.delete(`${config.api}/remove/${this.item.id}`).then(response => {
|
||||
this.item.rating = null;
|
||||
}, error => {
|
||||
alert(error);
|
||||
});
|
||||
}
|
||||
http.delete(`${config.api}/remove/${this.item.id}`).then(response => {
|
||||
this.rated = false;
|
||||
this.item.rating = null;
|
||||
this.item.watchlist = null;
|
||||
}, error => {
|
||||
alert(error);
|
||||
this.rated = false;
|
||||
});
|
||||
},
|
||||
|
||||
refreshInfos() {
|
||||
|
@ -56,7 +56,7 @@
|
||||
return this.initSuggestions();
|
||||
case 'trending':
|
||||
case 'upcoming':
|
||||
case 'current':
|
||||
case 'now-playing':
|
||||
return this.initContent(this.path);
|
||||
}
|
||||
},
|
||||
|
@ -14,11 +14,12 @@
|
||||
|
||||
<ul class="site-nav">
|
||||
<li><router-link to="/trending" @click.native="refresh('trending')">{{ lang('trending') }}</router-link></li>
|
||||
<li><router-link to="/current" @click.native="refresh('current')">{{ lang('current') }}</router-link></li>
|
||||
<li><router-link to="/now-playing" @click.native="refresh('now-playing')">{{ lang('now playing') }}</router-link></li>
|
||||
<li><router-link to="/upcoming" @click.native="refresh('upcoming')">{{ lang('upcoming') }}</router-link></li>
|
||||
</ul>
|
||||
|
||||
<ul class="site-nav-second">
|
||||
<li><router-link to="/watchlist" @click.native="refresh('watchlist')" exact>{{ lang('watchlist') }}</router-link></li>
|
||||
<li><router-link to="/tv" @click.native="refresh('tv')" exact>{{ lang('tv') }}</router-link></li>
|
||||
<li><router-link to="/movies" @click.native="refresh('movie')" exact>{{ lang('movies') }}</router-link></li>
|
||||
</ul>
|
||||
|
@ -3,10 +3,10 @@
|
||||
<span v-if="item.rating != null" :class="'item-rating rating-' + item.rating" @click="changeRating()">
|
||||
<i class="icon-rating"></i>
|
||||
</span>
|
||||
<span v-if="item.rating == null && item.tmdb_id && ! rated && auth" class="item-rating item-new" @click="addNewItem()">
|
||||
<span v-if="item.rating == null && item.tmdb_id && ! localRated && auth" class="item-rating item-new" @click="addNewItem()">
|
||||
<i class="icon-add"></i>
|
||||
</span>
|
||||
<span v-if="item.rating == null && item.tmdb_id && rated" class="item-rating item-new">
|
||||
<span v-if="(item.rating == null || item.watchlist) && item.tmdb_id && localRated" class="item-rating item-new">
|
||||
<span class="loader smallsize-loader"><i></i></span>
|
||||
</span>
|
||||
</div>
|
||||
@ -20,15 +20,20 @@
|
||||
const newItemMilliseconds = 200;
|
||||
|
||||
export default {
|
||||
props: ['item', 'set-item'],
|
||||
props: ['item', 'set-item', 'rated'],
|
||||
|
||||
data() {
|
||||
return {
|
||||
rated: false,
|
||||
auth: config.auth
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
localRated() {
|
||||
return this.rated;
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
this.saveNewRating = debounce(this.saveNewRating, ratingMilliseconds);
|
||||
this.addNewItem = debounce(this.addNewItem, newItemMilliseconds, true);
|
||||
@ -39,6 +44,7 @@
|
||||
if(this.auth) {
|
||||
this.prevRating = this.item.rating;
|
||||
this.item.rating = this.prevRating == 3 ? 1 : +this.prevRating + 1;
|
||||
this.item.watchlist = false;
|
||||
|
||||
this.saveNewRating();
|
||||
}
|
||||
@ -55,8 +61,8 @@
|
||||
if(this.auth) {
|
||||
this.rated = true;
|
||||
|
||||
http.post(`${config.api}/add`, {item: this.item}).then(value => {
|
||||
this.setItem(value.data);
|
||||
http.post(`${config.api}/add`, {item: this.item}).then(response => {
|
||||
this.setItem(response.data);
|
||||
this.rated = false;
|
||||
}, error => {
|
||||
if(error.status == 409) {
|
||||
|
@ -1,7 +1,23 @@
|
||||
import http from 'axios';
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
addToWatchlist(item) {
|
||||
if(this.auth) {
|
||||
this.rated = true;
|
||||
|
||||
http.post(`${config.api}/watchlist`, {item}).then(response => {
|
||||
this.setItem(response.data);
|
||||
this.rated = false;
|
||||
}, error => {
|
||||
alert(error.message);
|
||||
this.rated = false;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
displaySeason(item) {
|
||||
return item.media_type == 'tv' && item.rating != null && item.tmdb_id;
|
||||
return item.media_type == 'tv' && item.rating != null && item.tmdb_id && ! item.watchlist;
|
||||
},
|
||||
|
||||
openSeasonModal(item) {
|
||||
|
@ -20,6 +20,7 @@ export default new Router({
|
||||
// todo: use props for media type
|
||||
{ path: '/movies', component: Content, name: 'movie' },
|
||||
{ path: '/tv', component: Content, name: 'tv' },
|
||||
{ path: '/watchlist/:type?', component: Content, name: 'watchlist' },
|
||||
|
||||
{ path: '/movies/:tmdbId/:slug?', component: Subpage, name: 'subpage-movie', props: {mediaType: 'movie'} },
|
||||
{ path: '/tv/:tmdbId/:slug?', component: Subpage, name: 'subpage-tv', props: {mediaType: 'tv'} },
|
||||
@ -29,7 +30,7 @@ export default new Router({
|
||||
{ path: '/suggestions', component: TMDBContent, name: 'suggestions' },
|
||||
{ path: '/trending', component: TMDBContent, name: 'trending' },
|
||||
{ path: '/upcoming', component: TMDBContent, name: 'upcoming' },
|
||||
{ path: '/current', component: TMDBContent, name: 'current' },
|
||||
{ path: '/now-playing', component: TMDBContent, name: 'now-playing' },
|
||||
|
||||
{ path: '*', component: Content }
|
||||
]
|
||||
|
@ -30,7 +30,6 @@
|
||||
"style-loader": "^0.13.1",
|
||||
"url-loader": "^0.5.7",
|
||||
"vue-html-loader": "^1.2.3",
|
||||
"vue-loader": "^9.5.1",
|
||||
"vue-loader": "^9.9.5",
|
||||
"webpack": "^1.13.2"
|
||||
}
|
||||
|
@ -17,11 +17,15 @@
|
||||
|
||||
"trending": "الأكثر رواجا",
|
||||
"upcoming": "المقبلة",
|
||||
"current": "Current",
|
||||
"now playing": "Now Playing",
|
||||
"tv": "تلفاز",
|
||||
"movies": "أفلام",
|
||||
"last seen": "آخر المشاهدة",
|
||||
"best rated": "أفضل تقييم",
|
||||
"title": "Title",
|
||||
"release": "Release",
|
||||
"tmdb rating": "TMDb Rating",
|
||||
"imdb rating": "IMDb Rating",
|
||||
"change color": "تغيير الألوان",
|
||||
|
||||
"settings": "إعدادات",
|
||||
@ -52,8 +56,12 @@
|
||||
"watch trailer": "Watch Trailer",
|
||||
"trailer for": "Trailer for",
|
||||
"add to watchlist": "Add to Watchlist",
|
||||
"remove from watchlist": "Remove from Watchlist",
|
||||
"no tmdb rating": "No TMDb Rating",
|
||||
"loading imdb rating": "Loading IMDb Rating...",
|
||||
"no imdb rating": "No IMDb Rating",
|
||||
"overview": "Overview"
|
||||
"overview": "Overview",
|
||||
"watchlist": "Watchlist",
|
||||
"show watchlist": "Show Watchlist Items everywhere",
|
||||
"feedback": "If you have any feedback for us, please open an issue on"
|
||||
}
|
||||
|
@ -17,11 +17,15 @@
|
||||
|
||||
"trending": "Trender",
|
||||
"upcoming": "Kommende",
|
||||
"current": "Current",
|
||||
"now playing": "Now Playing",
|
||||
"tv": "TV",
|
||||
"movies": "Movies",
|
||||
"last seen": "Sidst set",
|
||||
"best rated": "Bedst bedømt",
|
||||
"title": "Title",
|
||||
"release": "Release",
|
||||
"tmdb rating": "TMDb Rating",
|
||||
"imdb rating": "IMDb Rating",
|
||||
"change color": "Skift farver",
|
||||
|
||||
"settings": "Indstillinger",
|
||||
@ -52,8 +56,12 @@
|
||||
"watch trailer": "Watch Trailer",
|
||||
"trailer for": "Trailer for",
|
||||
"add to watchlist": "Add to Watchlist",
|
||||
"remove from watchlist": "Remove from Watchlist",
|
||||
"no tmdb rating": "No TMDb Rating",
|
||||
"loading imdb rating": "Loading IMDb Rating...",
|
||||
"no imdb rating": "No IMDb Rating",
|
||||
"overview": "Overview"
|
||||
"overview": "Overview",
|
||||
"watchlist": "Watchlist",
|
||||
"show watchlist": "Show Watchlist Items everywhere",
|
||||
"feedback": "If you have any feedback for us, please open an issue on"
|
||||
}
|
||||
|
@ -17,11 +17,15 @@
|
||||
|
||||
"trending": "Beliebt",
|
||||
"upcoming": "Kommend",
|
||||
"current": "Aktuell",
|
||||
"now playing": "Aktuell",
|
||||
"tv": "TV",
|
||||
"movies": "Filme",
|
||||
"last seen": "Zuletzt gesehen",
|
||||
"best rated": "Am besten bewertet",
|
||||
"title": "Titel",
|
||||
"release": "Release",
|
||||
"tmdb rating": "TMDb Bewertung",
|
||||
"imdb rating": "IMDb Bewertung",
|
||||
"change color": "Farbmodus wechseln",
|
||||
|
||||
"settings": "Einstellungen",
|
||||
@ -52,8 +56,12 @@
|
||||
"watch trailer": "Trailer ansehen",
|
||||
"trailer for": "Trailer für",
|
||||
"add to watchlist": "Zur Watchlist",
|
||||
"remove from watchlist": "Entferne Watchlist",
|
||||
"no tmdb rating": "Kein TMDb Rating",
|
||||
"loading imdb rating": "Lade IMDb Rating...",
|
||||
"no imdb rating": "Kein IMDb Rating",
|
||||
"overview": "Zusammenfassung"
|
||||
"overview": "Zusammenfassung",
|
||||
"watchlist": "Watchlist",
|
||||
"show watchlist": "Zeige Watchlist Items überall an",
|
||||
"feedback": "Solltest du Feedback für uns haben, erstelle bitte ein neues issue auf"
|
||||
}
|
||||
|
@ -17,11 +17,15 @@
|
||||
|
||||
"trending": "Τάσεις",
|
||||
"upcoming": "Προσεχείς",
|
||||
"current": "Current",
|
||||
"now playing": "Now Playing",
|
||||
"tv": "TV",
|
||||
"movies": "Ταινίες",
|
||||
"last seen": "Τελευταία προβολή",
|
||||
"best rated": "Καλύτερη βαθμολογία",
|
||||
"title": "Title",
|
||||
"release": "Release",
|
||||
"tmdb rating": "TMDb Rating",
|
||||
"imdb rating": "IMDb Rating",
|
||||
"change color": "Αλλαγή χρωμάτων",
|
||||
|
||||
"settings": "Ρυθμίσεις",
|
||||
@ -52,8 +56,12 @@
|
||||
"watch trailer": "Watch Trailer",
|
||||
"trailer for": "Trailer for",
|
||||
"add to watchlist": "Add to Watchlist",
|
||||
"remove from watchlist": "Remove from Watchlist",
|
||||
"no tmdb rating": "No TMDb Rating",
|
||||
"loading imdb rating": "Loading IMDb Rating...",
|
||||
"no imdb rating": "No IMDb Rating",
|
||||
"overview": "Overview"
|
||||
"overview": "Overview",
|
||||
"watchlist": "Watchlist",
|
||||
"show watchlist": "Show Watchlist Items everywhere",
|
||||
"feedback": "If you have any feedback for us, please open an issue on"
|
||||
}
|
||||
|
@ -17,11 +17,15 @@
|
||||
|
||||
"trending": "Trending",
|
||||
"upcoming": "Upcoming",
|
||||
"current": "Current",
|
||||
"now playing": "Now Playing",
|
||||
"tv": "TV",
|
||||
"movies": "Movies",
|
||||
"last seen": "Last seen",
|
||||
"best rated": "Best rated",
|
||||
"title": "Title",
|
||||
"release": "Release",
|
||||
"tmdb rating": "TMDb Rating",
|
||||
"imdb rating": "IMDb Rating",
|
||||
"change color": "Change colors",
|
||||
|
||||
"settings": "Settings",
|
||||
@ -52,8 +56,12 @@
|
||||
"watch trailer": "Watch Trailer",
|
||||
"trailer for": "Trailer for",
|
||||
"add to watchlist": "Add to Watchlist",
|
||||
"remove from watchlist": "Remove from Watchlist",
|
||||
"no tmdb rating": "No TMDb Rating",
|
||||
"loading imdb rating": "Loading IMDb Rating...",
|
||||
"no imdb rating": "No IMDb Rating",
|
||||
"overview": "Overview"
|
||||
"overview": "Overview",
|
||||
"watchlist": "Watchlist",
|
||||
"show watchlist": "Show Watchlist Items everywhere",
|
||||
"feedback": "If you have any feedback for us, please open an issue on"
|
||||
}
|
@ -16,11 +16,15 @@
|
||||
|
||||
"trending": "Popular",
|
||||
"upcoming": "Próximamente",
|
||||
"current": "Current",
|
||||
"now playing": "Now Playing",
|
||||
"tv": "TV",
|
||||
"movies": "Películas",
|
||||
"last seen": "Última vista",
|
||||
"best rated": "Mejor calificada",
|
||||
"title": "Title",
|
||||
"release": "Release",
|
||||
"tmdb rating": "TMDb Rating",
|
||||
"imdb rating": "IMDb Rating",
|
||||
"change color": "Cambiar colores",
|
||||
|
||||
"settings": "Configuración",
|
||||
@ -50,8 +54,12 @@
|
||||
"watch trailer": "Watch Trailer",
|
||||
"trailer for": "Trailer for",
|
||||
"add to watchlist": "Add to Watchlist",
|
||||
"remove from watchlist": "Remove from Watchlist",
|
||||
"no tmdb rating": "No TMDb Rating",
|
||||
"loading imdb rating": "Loading IMDb Rating...",
|
||||
"no imdb rating": "No IMDb Rating",
|
||||
"overview": "Overview"
|
||||
"overview": "Overview",
|
||||
"watchlist": "Watchlist",
|
||||
"show watchlist": "Show Watchlist Items everywhere",
|
||||
"feedback": "If you have any feedback for us, please open an issue on"
|
||||
}
|
||||
|
@ -17,11 +17,15 @@
|
||||
|
||||
"trending": "Tendances",
|
||||
"upcoming": "Prochainement",
|
||||
"current": "Current",
|
||||
"now playing": "Now Playing",
|
||||
"tv": "Séries TV",
|
||||
"movies": "Films",
|
||||
"last seen": "Dernier film/épisode vu",
|
||||
"best rated": "Les mieux notés",
|
||||
"title": "Title",
|
||||
"release": "Release",
|
||||
"tmdb rating": "TMDb Rating",
|
||||
"imdb rating": "IMDb Rating",
|
||||
"change color": "Changer la couleur",
|
||||
|
||||
"settings": "Préférences",
|
||||
@ -52,8 +56,12 @@
|
||||
"watch trailer": "Watch Trailer",
|
||||
"trailer for": "Trailer for",
|
||||
"add to watchlist": "Add to Watchlist",
|
||||
"remove from watchlist": "Remove from Watchlist",
|
||||
"no tmdb rating": "No TMDb Rating",
|
||||
"loading imdb rating": "Loading IMDb Rating...",
|
||||
"no imdb rating": "No IMDb Rating",
|
||||
"overview": "Overview"
|
||||
"overview": "Overview",
|
||||
"watchlist": "Watchlist",
|
||||
"show watchlist": "Show Watchlist Items everywhere",
|
||||
"feedback": "If you have any feedback for us, please open an issue on"
|
||||
}
|
@ -17,11 +17,15 @@
|
||||
|
||||
"trending": "Trending",
|
||||
"upcoming": "Aankomende",
|
||||
"current": "Current",
|
||||
"now playing": "Now Playing",
|
||||
"tv": "TV",
|
||||
"movies": "Films",
|
||||
"last seen": "Laatst gezien",
|
||||
"best rated": "Best beoordeeld",
|
||||
"title": "Title",
|
||||
"release": "Release",
|
||||
"tmdb rating": "TMDb Rating",
|
||||
"imdb rating": "IMDb Rating",
|
||||
"change color": "Verander kleuren",
|
||||
|
||||
"settings": "Instellingen",
|
||||
@ -52,8 +56,12 @@
|
||||
"watch trailer": "Watch Trailer",
|
||||
"trailer for": "Trailer for",
|
||||
"add to watchlist": "Add to Watchlist",
|
||||
"remove from watchlist": "Remove from Watchlist",
|
||||
"no tmdb rating": "No TMDb Rating",
|
||||
"loading imdb rating": "Loading IMDb Rating...",
|
||||
"no imdb rating": "No IMDb Rating",
|
||||
"overview": "Overview"
|
||||
"overview": "Overview",
|
||||
"watchlist": "Watchlist",
|
||||
"show watchlist": "Show Watchlist Items everywhere",
|
||||
"feedback": "If you have any feedback for us, please open an issue on"
|
||||
}
|
||||
|
169
client/resources/sass/components/_content.scss
vendored
169
client/resources/sass/components/_content.scss
vendored
@ -95,9 +95,14 @@ main {
|
||||
}
|
||||
|
||||
.recommend-item,
|
||||
.add-to-watchlist {
|
||||
.add-to-watchlist,
|
||||
.remove-from-watchlist {
|
||||
opacity: .9;
|
||||
}
|
||||
|
||||
.is-on-watchlist {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -328,6 +333,7 @@ main {
|
||||
}
|
||||
|
||||
.add-to-watchlist,
|
||||
.remove-from-watchlist,
|
||||
.edit-item {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
@ -359,6 +365,28 @@ main {
|
||||
}
|
||||
}
|
||||
|
||||
.remove-from-watchlist {
|
||||
//opacity: 1 !important;
|
||||
}
|
||||
|
||||
.is-on-watchlist {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
background: #238cce;
|
||||
padding: 4px 5px;
|
||||
|
||||
@include transition(opacity);
|
||||
|
||||
@include media(3) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
i {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-item {
|
||||
background: $rating2;
|
||||
opacity: 1;
|
||||
@ -454,8 +482,132 @@ main {
|
||||
color: $dark;
|
||||
}
|
||||
|
||||
.content-submenu {
|
||||
margin-bottom: 30px;
|
||||
margin-top: -30px;
|
||||
position: relative;
|
||||
z-index: 150;
|
||||
}
|
||||
|
||||
.sort-wrap {
|
||||
float: right;
|
||||
|
||||
.icon-sort-time,
|
||||
.icon-sort-star {
|
||||
float: left;
|
||||
width: 32px;
|
||||
height: 30px;
|
||||
margin: 0 0 0 15px;
|
||||
cursor: pointer;
|
||||
opacity: .6;
|
||||
|
||||
@include transition(opacity);
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:active {
|
||||
opacity: .4;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sort-direction {
|
||||
float: left;
|
||||
padding: 0 10px;
|
||||
cursor: pointer;
|
||||
font-size: 18px;
|
||||
color: #888;
|
||||
|
||||
&:active {
|
||||
opacity: .6;
|
||||
}
|
||||
|
||||
.dark & {
|
||||
color: #626262;
|
||||
}
|
||||
|
||||
i {
|
||||
float: left;
|
||||
font-style: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.filter-wrap {
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.current-filter {
|
||||
float: left;
|
||||
padding: 7px 9px;
|
||||
color: #888;
|
||||
font-size: 14px;
|
||||
|
||||
.dark & {
|
||||
color: #626262;
|
||||
}
|
||||
}
|
||||
|
||||
.arrow-down {
|
||||
display: inline-block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
margin-left: 2px;
|
||||
vertical-align: middle;
|
||||
border-top: 4px solid;
|
||||
border-right: 4px solid transparent;
|
||||
border-left: 4px solid transparent;
|
||||
}
|
||||
|
||||
.all-filters {
|
||||
position: absolute;
|
||||
top: 70%;
|
||||
right: 0;
|
||||
background: $main2;
|
||||
list-style: none;
|
||||
min-width: 170px;
|
||||
//display: none;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
|
||||
@include transition(opacity, top);
|
||||
|
||||
&.active {
|
||||
//display: block;
|
||||
opacity: 1;
|
||||
top: 100%;
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
li {
|
||||
float: left;
|
||||
padding: 5px 10px;
|
||||
color: rgba(#fff, .9);
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid rgba(#fff, .3);
|
||||
|
||||
@include transition(background);
|
||||
|
||||
&:hover {
|
||||
background: $main1;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.current-version {
|
||||
margin: 0 0 10px 0;
|
||||
margin: 0;
|
||||
|
||||
span {
|
||||
color: gray;
|
||||
@ -511,6 +663,17 @@ main {
|
||||
float: left;
|
||||
font-size: 14px;
|
||||
color: gray;
|
||||
clear: both;
|
||||
margin: 10px 0;
|
||||
|
||||
a {
|
||||
color: $main1;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
float: left;
|
||||
@ -575,7 +738,7 @@ main {
|
||||
}
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
.setting-box {
|
||||
float: left;
|
||||
width: 100%;
|
||||
margin: 0 0 10px 0;
|
||||
|
12
client/resources/sass/components/_subpage.scss
vendored
12
client/resources/sass/components/_subpage.scss
vendored
@ -117,6 +117,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
.icon-watchlist-remove {
|
||||
background: url(../../../public/assets/img/watchlist-remove.png);
|
||||
width: 14px;
|
||||
height: 11px;
|
||||
float: left;
|
||||
margin: 7px 7px 0 0;
|
||||
|
||||
@include media(4) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.big-teaser-buttons {
|
||||
float: left;
|
||||
clear: both;
|
||||
|
2
public/assets/app.css
vendored
2
public/assets/app.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
public/assets/img/watchlist-remove.png
Normal file
BIN
public/assets/img/watchlist-remove.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 300 B |
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user