wip-feat: adds functionality to Monitor button
This commit is contained in:
93
assets/controllers/monitor_button_controller.js
Normal file
93
assets/controllers/monitor_button_controller.js
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import { Controller } from '@hotwired/stimulus';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following line makes this controller "lazy": it won't be downloaded until needed
|
||||||
|
* See https://symfony.com/bundles/StimulusBundle/current/index.html#lazy-stimulus-controllers
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* stimulusFetch: 'lazy' */
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = ['button', 'options']
|
||||||
|
static outlets = ['result-filter']
|
||||||
|
static values = {
|
||||||
|
tmdbId: String,
|
||||||
|
imdbId: String,
|
||||||
|
title: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
// Called once when the controller is first instantiated (per element)
|
||||||
|
|
||||||
|
// Here you can initialize variables, create scoped callables for event
|
||||||
|
// listeners, instantiate external libraries, etc.
|
||||||
|
// this._fooBar = this.fooBar.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
// Called every time the controller is connected to the DOM
|
||||||
|
// (on page load, when it's added to the DOM, moved in the DOM, etc.)
|
||||||
|
|
||||||
|
// Here you can add event listeners on the element or target elements,
|
||||||
|
// add or remove classes, attributes, dispatch custom events, etc.
|
||||||
|
// this.fooTarget.addEventListener('click', this._fooBar)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add custom controller actions here
|
||||||
|
// fooBar() { this.fooTarget.classList.toggle(this.bazClass) }
|
||||||
|
|
||||||
|
disconnect() {
|
||||||
|
// Called anytime its element is disconnected from the DOM
|
||||||
|
// (on page change, when it's removed from or moved in the DOM, etc.)
|
||||||
|
|
||||||
|
// Here you should remove all event listeners added in "connect()"
|
||||||
|
// this.fooTarget.removeEventListener('click', this._fooBar)
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle() {
|
||||||
|
this.optionsTarget.classList.toggle('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
async monitorSeries() {
|
||||||
|
await this.makeMonitor({
|
||||||
|
tmdbId: this.tmdbIdValue,
|
||||||
|
imdbId: this.imdbIdValue,
|
||||||
|
title: this.titleValue,
|
||||||
|
monitorType: 'tvshows',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async monitorSeason() {
|
||||||
|
await this.makeMonitor({
|
||||||
|
tmdbId: this.tmdbIdValue,
|
||||||
|
imdbId: this.imdbIdValue,
|
||||||
|
title: this.titleValue,
|
||||||
|
monitorType: 'tvseason',
|
||||||
|
season: this.resultFilterOutlet.activeFilter['season'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async monitorEpisode() {
|
||||||
|
// ToDo: figure out how to set episode
|
||||||
|
await this.makeMonitor({
|
||||||
|
tmdbId: this.tmdbIdValue,
|
||||||
|
imdbId: this.imdbIdValue,
|
||||||
|
title: this.titleValue,
|
||||||
|
monitorType: 'tvepisode',
|
||||||
|
season: this.resultFilterOutlet.activeFilter['season'],
|
||||||
|
episode: '',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async makeMonitor(body) {
|
||||||
|
const response = await fetch('/api/monitor', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Accept': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body)
|
||||||
|
});
|
||||||
|
|
||||||
|
return await response.json();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,10 @@
|
|||||||
framework:
|
framework:
|
||||||
secret: '%env(APP_SECRET)%'
|
secret: '%env(APP_SECRET)%'
|
||||||
|
|
||||||
|
serializer:
|
||||||
|
default_context:
|
||||||
|
enable_max_depth: true
|
||||||
|
|
||||||
trusted_proxies: 'private_ranges'
|
trusted_proxies: 'private_ranges'
|
||||||
# trust *all* "X-Forwarded-*" headers
|
# trust *all* "X-Forwarded-*" headers
|
||||||
trusted_headers: [ 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-prefix' ]
|
trusted_headers: [ 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-prefix' ]
|
||||||
|
|||||||
@@ -13,3 +13,11 @@ controllersUser:
|
|||||||
type: attribute
|
type: attribute
|
||||||
defaults:
|
defaults:
|
||||||
schemes: ['https']
|
schemes: ['https']
|
||||||
|
|
||||||
|
controllersDownload:
|
||||||
|
resource:
|
||||||
|
path: ../src/Download/Framework/Controller
|
||||||
|
namespace: App\Download\Framework\Controller
|
||||||
|
type: attribute
|
||||||
|
defaults:
|
||||||
|
schemes: ['https']
|
||||||
|
|||||||
@@ -5,16 +5,37 @@ namespace App\Download\Framework\Controller;
|
|||||||
use App\Download\Action\Handler\AddMonitorHandler;
|
use App\Download\Action\Handler\AddMonitorHandler;
|
||||||
use App\Download\Action\Input\AddMonitorInput;
|
use App\Download\Action\Input\AddMonitorInput;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
|
use Symfony\Component\Mercure\HubInterface;
|
||||||
|
use Symfony\Component\Mercure\Update;
|
||||||
use Symfony\Component\Routing\Attribute\Route;
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
use Twig\Environment;
|
||||||
|
|
||||||
class ApiController extends AbstractController
|
class ApiController extends AbstractController
|
||||||
{
|
{
|
||||||
#[Route('/monitor', name: 'app_add_movie_monitor', methods: ['POST'])]
|
public function __construct(
|
||||||
|
#[Autowire(service: 'twig')]
|
||||||
|
private readonly Environment $renderer,
|
||||||
|
private readonly HubInterface $hub,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
#[Route('/api/monitor', name: 'api_monitor', methods: ['POST'])]
|
||||||
public function addMonitor(
|
public function addMonitor(
|
||||||
AddMonitorInput $input,
|
AddMonitorInput $input,
|
||||||
AddMonitorHandler $handler,
|
AddMonitorHandler $handler,
|
||||||
|
HubInterface $hub,
|
||||||
) {
|
) {
|
||||||
$response = $handler->handle($input->toCommand());
|
$response = $handler->handle($input->toCommand());
|
||||||
|
|
||||||
|
$hub->publish(new Update(
|
||||||
|
'alerts',
|
||||||
|
$this->renderer->render('broadcast/Alert.html.twig', [
|
||||||
|
'alert_id' => uniqid(),
|
||||||
|
'title' => 'Success',
|
||||||
|
'message' => "New monitor added for {$input->title}",
|
||||||
|
])
|
||||||
|
));
|
||||||
|
|
||||||
return $this->json([
|
return $this->json([
|
||||||
'status' => 200,
|
'status' => 200,
|
||||||
'message' => $response
|
'message' => $response
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ use App\Download\Framework\Repository\MonitorRepository;
|
|||||||
use App\User\Framework\Entity\User;
|
use App\User\Framework\Entity\User;
|
||||||
use Doctrine\DBAL\Types\Types;
|
use Doctrine\DBAL\Types\Types;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use Symfony\Component\Serializer\Attribute\Ignore;
|
||||||
|
use Symfony\Component\Serializer\Attribute\MaxDepth;
|
||||||
|
|
||||||
#[ORM\Entity(repositoryClass: MonitorRepository::class)]
|
#[ORM\Entity(repositoryClass: MonitorRepository::class)]
|
||||||
class Monitor
|
class Monitor
|
||||||
@@ -15,6 +17,7 @@ class Monitor
|
|||||||
#[ORM\Column]
|
#[ORM\Column]
|
||||||
private ?int $id = null;
|
private ?int $id = null;
|
||||||
|
|
||||||
|
#[Ignore]
|
||||||
#[ORM\ManyToOne(inversedBy: 'yes')]
|
#[ORM\ManyToOne(inversedBy: 'yes')]
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
private ?User $user = null;
|
private ?User $user = null;
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
|
|
||||||
{% if results.media.mediaType == "tvshows" %}
|
{% if results.media.mediaType == "tvshows" %}
|
||||||
<div class="flex flex-row gap-2 justify-end px-8">
|
<div class="flex flex-row gap-2 justify-end px-8">
|
||||||
<button class="px-1.5 py-1 bg-green-600 rounded-md text-sm"
|
<button class="px-1.5 py-1 bg-green-600 hover:bg-green-700 rounded-md text-sm"
|
||||||
{{ stimulus_target('result_filter', 'downloadSelected') }}
|
{{ stimulus_target('result_filter', 'downloadSelected') }}
|
||||||
{{ stimulus_action('result_filter', 'downloadSelectedEpisodes', 'click') }}
|
{{ stimulus_action('result_filter', 'downloadSelectedEpisodes', 'click') }}
|
||||||
>Download Selected</button>
|
>Download Selected</button>
|
||||||
|
|||||||
@@ -14,18 +14,45 @@
|
|||||||
<h3 class="text-xl font-medium leading-tight font-bold text-gray-50">
|
<h3 class="text-xl font-medium leading-tight font-bold text-gray-50">
|
||||||
{{ results.media.title }} - {{ results.media.year }}
|
{{ results.media.title }} - {{ results.media.year }}
|
||||||
</h3>
|
</h3>
|
||||||
<button class="px-1.5 py-1 bg-green-600 text-white rounded-md cursor-pointer"
|
|
||||||
{{ stimulus_controller('monitor', {
|
|
||||||
tmdbId: results.media.tmdbId,
|
<div {{ stimulus_controller('monitor_button', {
|
||||||
imdbId: results.media.imdbId,
|
tmdbId: results.media.tmdbId,
|
||||||
title: results.media.title
|
imdbId: results.media.imdbId,
|
||||||
}) }}
|
title: results.media.title,
|
||||||
{% if results.media.mediaType == "movies" %}
|
})}}
|
||||||
{{ stimulus_action('monitor', 'addMovieMonitor', 'click') }}
|
data-monitor-button-result-filter-outlet="#filter"
|
||||||
{% endif %}
|
|
||||||
>
|
>
|
||||||
Monitor
|
<button data-monitor-button-target="button" {{ stimulus_action('monitor_button', 'toggle', 'click') }} class="h-8 text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-2 py-1.5 text-center inline-flex items-center dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800" type="button">
|
||||||
</button>
|
Monitor
|
||||||
|
<svg class="w-2.5 h-2.5 ms-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
|
||||||
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Dropdown menu -->
|
||||||
|
<div data-monitor-button-target="options" class="absolute mt-1 right-12 z-40 hidden bg-white divide-y rounded-lg shadow-sm w-44 dark:bg-green-600 backdrop-filter backdrop-blur-md bg-opacity-60">
|
||||||
|
<ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="dropdownDefaultButton">
|
||||||
|
<li {{ stimulus_action('monitor_button', 'monitorSeries', 'click') }}>
|
||||||
|
<button class="px-4 py-2 hover:bg-green-700 w-full text-left">
|
||||||
|
Entire Series
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li {{ stimulus_action('monitor_button', 'monitorSeason', 'click') }}>
|
||||||
|
<button class="px-4 py-2 hover:bg-green-700 w-full text-left">
|
||||||
|
Season
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li {{ stimulus_action('monitor_button', 'monitorEpisode', 'click') }}>
|
||||||
|
<button class="px-4 py-2 hover:bg-green-700 w-full text-left">
|
||||||
|
Episode
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p class="text-gray-50">
|
<p class="text-gray-50">
|
||||||
{{ results.media.description }}
|
{{ results.media.description }}
|
||||||
|
|||||||
Reference in New Issue
Block a user