1
0
mirror of https://github.com/devfake/flox.git synced 2024-11-14 22:22:39 +01:00

improve last seen filter (#56)

* prepare migrations and relation

* update and order by new last_seen_at field

* add tests

* update production files
This commit is contained in:
Viktor Geringer 2017-02-26 10:09:54 +01:00 committed by Tim Meier
parent cb119e2ff4
commit ec2f87daef
12 changed files with 212 additions and 36 deletions

View File

@ -2,13 +2,10 @@
namespace App;
use App\Services\TMDB;
use Illuminate\Database\Eloquent\Model;
class Episode extends Model {
public $timestamps = false;
protected $fillable = [
'tmdb_id',
'name',
@ -18,8 +15,9 @@
'episode_tmdb_id',
'seen',
'season_tmdb_id',
'created_at',
'subtitles',
'created_at',
'updated_at',
];
/**
@ -39,12 +37,20 @@
'episode_number' => $episode->episode_number,
'name' => $episode->name,
'tmdb_id' => $tmdbId,
'created_at' => time(),
]);
}
}
}
/*
* Relations
*/
public function item()
{
return $this->belongsTo(Item::class, 'tmdb_id', 'tmdb_id');
}
/*
* Scopes
*/

View File

@ -33,10 +33,11 @@
/**
* Return all items with pagination.
*
* @param ItemService $item
* @param ItemService $itemService
* @param $type
* @param $orderBy
* @return mixed
* @internal param ItemService $item
*/
public function items(ItemService $itemService, $type, $orderBy)
{
@ -138,6 +139,8 @@
/**
* Toggle all episodes of an season as seen / unseen.
*
* @param EpisodeService $episode
*/
public function toggleSeason(EpisodeService $episode)
{

View File

@ -9,6 +9,7 @@
use App\Services\Storage;
use App\Services\TMDB;
use App\Setting;
use Carbon\Carbon;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ConnectException;
use Illuminate\Contracts\Routing\ResponseFactory;
@ -79,6 +80,11 @@
if(isset($data->items)) {
$this->item->truncate();
foreach($data->items as $item) {
// Fallback if export was from an older version of flox.
if( ! isset($item->last_seen_at)) {
$item->last_seen_at = Carbon::createFromTimestamp($item->created_at);
}
$this->item->create((array) $item);
$this->storage->downloadPoster($item->poster);
}

View File

@ -2,8 +2,7 @@
namespace App;
use App\Services\Storage;
use App\Services\TMDB;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
@ -12,7 +11,7 @@
// Uncomment this if you are using Laravel Scout.
//use Searchable;
public $timestamps = false;
protected $dates = ['last_seen'];
protected $fillable = [
'tmdb_id',
@ -22,11 +21,13 @@
'media_type',
'rating',
'released',
'created_at',
'genre',
'fp_name',
'src',
'subtitles',
'last_seen_at',
'created_at',
'updated_at',
];
/**
@ -46,7 +47,7 @@
'rating' => 0,
'released' => $data['released'],
'genre' => $data['genre'],
'created_at' => time(),
'last_seen_at' => Carbon::now(),
]);
}
@ -65,9 +66,20 @@
'poster' => '',
'rating' => 1,
'released' => time(),
'created_at' => time(),
'src' => $data['src'],
'subtitles' => $data['subtitles'],
'last_seen_at' => Carbon::now(),
]);
}
/**
* @param $tmdbId
* @return mixed
*/
public function updateLastSeenAt($tmdbId)
{
return $this->where('tmdb_id', $tmdbId)->update([
'last_seen_at' => Carbon::now(),
]);
}

View File

@ -3,6 +3,7 @@
namespace App\Services\Models;
use App\Episode as Model;
use App\Item;
use App\Services\TMDB;
use App\Setting;
@ -10,15 +11,22 @@
private $model;
private $tmdb;
private $item;
/**
* @param Model $model
* @param TMDB $tmdb
* @param Item $item
*
* @internal param ItemService $itemService
*
* @internal param Item $item
*/
public function __construct(Model $model, TMDB $tmdb)
public function __construct(Model $model, TMDB $tmdb, Item $item)
{
$this->model = $model;
$this->tmdb = $tmdb;
$this->item = $item;
}
/**
@ -71,6 +79,11 @@
$episode = $this->model->find($id);
if($episode) {
// Update the parent relation only if we mark the episode as seen.
if( ! $episode->seen) {
$this->item->updateLastSeenAt($episode->tmdb_id);
}
return $episode->update([
'seen' => ! $episode->seen,
]);
@ -86,6 +99,11 @@
{
$episodes = $this->model->findSeason($tmdbId, $season)->get();
// Update the parent relation only if we mark the episode as seen.
if($seen) {
$this->item->updateLastSeenAt($episodes[0]->tmdb_id);
}
$episodes->each(function($episode) use ($seen) {
$episode->update([
'seen' => $seen,

View File

@ -1,5 +1,7 @@
<?php
use Carbon\Carbon;
$factory->define(App\User::class, function(Faker\Generator $faker) {
static $password;
@ -25,7 +27,7 @@
'rating' => 1,
'genre' => '',
'released' => time(),
'created_at' => time(),
'last_seen_at' => Carbon::now(),
'src' => null,
];
});
@ -35,7 +37,6 @@
'name' => $faker->name,
'season_tmdb_id' => 1,
'episode_tmdb_id' => 1,
'created_at' => time(),
'src' => null,
];
});

View File

@ -0,0 +1,26 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddTimestampsToEpisodes extends Migration
{
public function up()
{
Schema::table('episodes', function (Blueprint $table) {
$table->dropColumn('created_at');
});
Schema::table('episodes', function (Blueprint $table) {
$table->timestamps();
});
}
public function down()
{
Schema::table('episodes', function (Blueprint $table) {
//
});
}
}

View File

@ -0,0 +1,49 @@
<?php
use App\Item;
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddTimestampsAndLastSeenAtToItems extends Migration {
private $items;
public function up()
{
$this->items = Item::get(['id', 'created_at']);
Schema::table('items', function (Blueprint $table) {
$table->dropColumn('created_at');
});
Schema::table('items', function (Blueprint $table) {
$table->timestamps();
$table->timestamp('last_seen_at')->nullable();
});
$this->repopulateCreatedAt();
}
/**
* We can't change an integer field to a timestamp field.
* So we need to remove the current created_at integer field,
* create the new timestamp fields, and repopulate the old created_at data.
*/
private function repopulateCreatedAt()
{
$this->items->map(function ($item) {
$item->created_at = $item->created_at;
$item->updated_at = $item->created_at;
$item->last_seen_at = $item->created_at;
$item->save();
});
}
public function down()
{
Schema::table('items', function (Blueprint $table) {
//
});
}
}

View File

@ -1,6 +1,7 @@
<?php
use App\Episode;
use App\Item;
use App\Services\Models\EpisodeService;
use App\Services\Models\ItemService;
use App\Services\TMDB;
@ -11,12 +12,16 @@
use DatabaseMigrations;
private $episode;
private $episodeService;
private $item;
public function setUp()
{
parent::setUp();
$this->episode = app(Episode::class);
$this->episodeService = app(EpisodeService::class);
$this->item = app(Item::class);
}
/** @test */
@ -39,12 +44,11 @@
public function it_should_set_a_episode_as_seen_or_unseen()
{
$this->createTv();
$episodeService = app(EpisodeService::class);
$episode1 = $this->episode->find(1);
$episodeService->toggleSeen(1);
$this->episodeService->toggleSeen(1);
$episode2 = $this->episode->find(1);
$episodeService->toggleSeen(1);
$this->episodeService->toggleSeen(1);
$episode3 = $this->episode->find(1);
$this->assertEquals(0, $episode1->seen);
@ -56,15 +60,14 @@
public function it_should_set_all_episodes_of_a_season_as_seen_or_unseen()
{
$this->createTv();
$episodeService = app(EpisodeService::class);
$season = 1;
$tmdbId = 1399;
$episodes1 = $this->episode->where('season_number', $season)->get();
$episodeService->toggleSeason($tmdbId, 1, 1);
$this->episodeService->toggleSeason($tmdbId, $season, 1);
$episodes2 = $this->episode->where('season_number', $season)->get();
$episodeService->toggleSeason($tmdbId, 1, 0);
$this->episodeService->toggleSeason($tmdbId, $season, 0);
$episodes3 = $this->episode->where('season_number', $season)->get();
$episodes1->each(function($episode) {
@ -82,16 +85,68 @@
public function it_should_remove_episodes()
{
$this->createTv();
$episodeService = app(EpisodeService::class);
$episodes1 = $this->episode->findByTmdbId(1399)->get();
$episodeService->remove(1399);
$this->episodeService->remove(1399);
$episodes2 = $this->episode->findByTmdbId(1399)->get();
$this->assertNotNull($episodes1);
$this->assertCount(0, $episodes2);
}
/** @test */
public function it_should_update_items_from_one_episode()
{
$this->createTv();
$item = $this->item->find(1);
sleep(1);
$this->episodeService->toggleSeen(1);
$itemUpdated = $this->item->find(1);
$this->assertNotEquals($itemUpdated->last_seen_at, $item->last_seen_at);
}
/** @test */
public function it_should_update_items_only_on_seen_from_one_episode()
{
$this->createTv();
$this->episodeService->toggleSeen(1);
$item = $this->item->find(1);
sleep(1);
$this->episodeService->toggleSeen(1);
$itemUpdated = $this->item->find(1);
$this->assertEquals($itemUpdated->last_seen_at, $item->last_seen_at);
}
/** @test */
public function it_should_update_items_from_all_episodes()
{
$this->createTv();
$item = $this->item->find(1);
sleep(1);
$this->episodeService->toggleSeason(1399, 1, 1);
$itemUpdated = $this->item->find(1);
$this->assertNotEquals($itemUpdated->last_seen_at, $item->last_seen_at);
}
/** @test */
public function it_should_update_items_only_on_seen_from_all_episodes()
{
$this->createTv();
$item = $this->item->find(1);
sleep(1);
$this->episodeService->toggleSeason(1399, 1, 0);
$itemUpdated = $this->item->find(1);
$this->assertEquals($itemUpdated->last_seen_at, $item->last_seen_at);
}
private function createTmdbMock()
{
// Mock this to avoid unknown requests to TMDb (get seasons and then get episodes for each season)

View File

@ -6,7 +6,7 @@
</router-link>
<span class="sort-wrap">
<i :title="lang('last seen')" class="icon-sort-time" :class="{active: userFilter == 'created_at'}" @click="setUserFilter('created_at')"></i>
<i :title="lang('last seen')" class="icon-sort-time" :class="{active: userFilter == 'last_seen_at'}" @click="setUserFilter('last_seen_at')"></i>
<i :title="lang('best rated')" class="icon-sort-star" :class="{active: userFilter == 'rating'}" @click="setUserFilter('rating')"></i>
<span :title="lang('change color')" class="icon-constrast" @click="toggleColorScheme()"><i></i></span>
</span>
@ -59,7 +59,7 @@
checkForUserFilter() {
if( ! localStorage.getItem('filter')) {
localStorage.setItem('filter', 'created_at');
localStorage.setItem('filter', 'last_seen_at');
}
this.SET_USER_FILTER(localStorage.getItem('filter'));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long