Compare commits
2 Commits
dev-delete
...
v0.15.16
| Author | SHA1 | Date | |
|---|---|---|---|
| b1ccf3bf00 | |||
| 785794790c |
@@ -1,24 +0,0 @@
|
|||||||
import { Controller } from '@hotwired/stimulus';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The following line makes this controller "lazy": it won't be downloaded until needed
|
|
||||||
* See https://github.com/symfony/stimulus-bridge#lazy-controllers
|
|
||||||
*/
|
|
||||||
/* stimulusFetch: 'lazy' */
|
|
||||||
export default class extends Controller {
|
|
||||||
static values = {
|
|
||||||
title: String,
|
|
||||||
tmdbId: String,
|
|
||||||
imdbId: String,
|
|
||||||
mediaType: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
addMovieMonitor() {
|
|
||||||
console.log(`/monitor/movies/${this.tmdbIdValue}/${this.imdbIdValue}/${encodeURI(this.titleValue)}`)
|
|
||||||
fetch(`/monitor/movies/${this.tmdbIdValue}/${this.imdbIdValue}/${encodeURI(this.titleValue)}`)
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(json => {
|
|
||||||
console.log(json)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
14
assets/controllers/monitor_list_controller.js
Normal file
14
assets/controllers/monitor_list_controller.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { Controller } from '@hotwired/stimulus';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following line makes this controller "lazy": it won't be downloaded until needed
|
||||||
|
* See https://github.com/symfony/stimulus-bridge#lazy-controllers
|
||||||
|
*/
|
||||||
|
/* stimulusFetch: 'lazy' */
|
||||||
|
export default class extends Controller {
|
||||||
|
deleteMonitor(data) {
|
||||||
|
fetch(`/api/monitor/${data.params.id}`, {method: 'DELETE'})
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(json => console.debug(json));
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/Monitor/Action/Command/DeleteMonitorCommand.php
Normal file
13
src/Monitor/Action/Command/DeleteMonitorCommand.php
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Monitor\Action\Command;
|
||||||
|
|
||||||
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
|
|
||||||
|
/** @implements CommandInterface<DeleteMonitorCommand> */
|
||||||
|
class DeleteMonitorCommand implements CommandInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $monitorId,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
36
src/Monitor/Action/Handler/DeleteMonitorHandler.php
Normal file
36
src/Monitor/Action/Handler/DeleteMonitorHandler.php
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Monitor\Action\Handler;
|
||||||
|
|
||||||
|
use App\Monitor\Action\Command\AddMonitorCommand;
|
||||||
|
use App\Monitor\Action\Command\DeleteMonitorCommand;
|
||||||
|
use App\Monitor\Action\Result\AddMonitorResult;
|
||||||
|
use App\Monitor\Action\Result\DeleteMonitorResult;
|
||||||
|
use App\Monitor\Framework\Entity\Monitor;
|
||||||
|
use App\Monitor\Framework\Repository\MonitorRepository;
|
||||||
|
use App\User\Framework\Repository\UserRepository;
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
|
use OneToMany\RichBundle\Contract\HandlerInterface;
|
||||||
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||||
|
|
||||||
|
/** @implements HandlerInterface<DeleteMonitorCommand, DeleteMonitorResult> */
|
||||||
|
readonly class DeleteMonitorHandler implements HandlerInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private MonitorRepository $monitorRepository,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function handle(CommandInterface $command): ResultInterface
|
||||||
|
{
|
||||||
|
$monitor = $this->monitorRepository->find($command->monitorId);
|
||||||
|
$this->monitorRepository->getEntityManager()->remove($monitor);
|
||||||
|
$this->monitorRepository->getEntityManager()->flush();
|
||||||
|
|
||||||
|
return new DeleteMonitorResult(
|
||||||
|
status: 'OK',
|
||||||
|
result: [],
|
||||||
|
monitor: $monitor
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/Monitor/Action/Input/DeleteMonitorInput.php
Normal file
24
src/Monitor/Action/Input/DeleteMonitorInput.php
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Monitor\Action\Input;
|
||||||
|
|
||||||
|
use App\Monitor\Action\Command\DeleteMonitorCommand;
|
||||||
|
use OneToMany\RichBundle\Attribute\SourceRoute;
|
||||||
|
use OneToMany\RichBundle\Contract\CommandInterface;
|
||||||
|
use OneToMany\RichBundle\Contract\InputInterface;
|
||||||
|
|
||||||
|
/** @implements InputInterface<DeleteMonitorInput, DeleteMonitorCommand> */
|
||||||
|
class DeleteMonitorInput implements InputInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
#[SourceRoute('monitorId')]
|
||||||
|
public int $monitorId,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function toCommand(): CommandInterface
|
||||||
|
{
|
||||||
|
return new DeleteMonitorCommand(
|
||||||
|
$this->monitorId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/Monitor/Action/Result/DeleteMonitorResult.php
Normal file
15
src/Monitor/Action/Result/DeleteMonitorResult.php
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Monitor\Action\Result;
|
||||||
|
|
||||||
|
use App\Monitor\Framework\Entity\Monitor;
|
||||||
|
use OneToMany\RichBundle\Contract\ResultInterface;
|
||||||
|
|
||||||
|
class DeleteMonitorResult implements ResultInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $status,
|
||||||
|
public array $result,
|
||||||
|
public Monitor $monitor,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
@@ -2,8 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Monitor\Framework\Controller;
|
namespace App\Monitor\Framework\Controller;
|
||||||
|
|
||||||
|
use App\Download\Action\Input\DeleteDownloadInput;
|
||||||
use App\Monitor\Action\Handler\AddMonitorHandler;
|
use App\Monitor\Action\Handler\AddMonitorHandler;
|
||||||
|
use App\Monitor\Action\Handler\DeleteMonitorHandler;
|
||||||
use App\Monitor\Action\Input\AddMonitorInput;
|
use App\Monitor\Action\Input\AddMonitorInput;
|
||||||
|
use App\Monitor\Action\Input\DeleteMonitorInput;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Bundle\SecurityBundle\Security;
|
use Symfony\Bundle\SecurityBundle\Security;
|
||||||
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
use Symfony\Component\DependencyInjection\Attribute\Autowire;
|
||||||
@@ -43,4 +46,27 @@ class ApiController extends AbstractController
|
|||||||
'message' => $response
|
'message' => $response
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route('/api/monitor/{monitorId}', name: 'api_monitor_delete', methods: ['DELETE'])]
|
||||||
|
public function deleteMonitor(
|
||||||
|
DeleteMonitorInput $input,
|
||||||
|
DeleteMonitorHandler $handler,
|
||||||
|
HubInterface $hub,
|
||||||
|
) {
|
||||||
|
$response = $handler->handle($input->toCommand());
|
||||||
|
|
||||||
|
$hub->publish(new Update(
|
||||||
|
'alerts',
|
||||||
|
$this->renderer->render('broadcast/Alert.stream.html.twig', [
|
||||||
|
'alert_id' => uniqid(),
|
||||||
|
'title' => 'Success',
|
||||||
|
'message' => "New monitor added for {$response->monitor->getTitle()}",
|
||||||
|
])
|
||||||
|
));
|
||||||
|
|
||||||
|
return $this->json([
|
||||||
|
'status' => 200,
|
||||||
|
'message' => $response
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ 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\Ignore;
|
||||||
|
use Symfony\UX\Turbo\Attribute\Broadcast;
|
||||||
|
|
||||||
|
#[Broadcast(template: 'broadcast/Monitor.stream.html.twig')]
|
||||||
#[ORM\Entity(repositoryClass: MonitorRepository::class)]
|
#[ORM\Entity(repositoryClass: MonitorRepository::class)]
|
||||||
class Monitor
|
class Monitor
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
<twig:StatusBadge color="green" status="Complete" />
|
<twig:StatusBadge color="green" status="Complete" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
</turbo-stream>
|
</turbo-stream>
|
||||||
@@ -35,6 +36,7 @@
|
|||||||
<div class="text-green-700 rounded-sm text-bold text-gray-950 text-center bg-green-600 h-5" style="width:{{ entity.progress }}%">{{ entity.progress }}%</div>
|
<div class="text-green-700 rounded-sm text-bold text-gray-950 text-center bg-green-600 h-5" style="width:{{ entity.progress }}%">{{ entity.progress }}%</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
<td></td>
|
||||||
</template>
|
</template>
|
||||||
</turbo-stream>
|
</turbo-stream>
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -59,6 +61,15 @@
|
|||||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-gray-50">
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800 dark:text-gray-50">
|
||||||
<twig:StatusBadge color="green" status="Complete" />
|
<twig:StatusBadge color="green" status="Complete" />
|
||||||
</td>
|
</td>
|
||||||
|
<td class="px-6 py-4 flex flex-row align-middle justify-center">
|
||||||
|
<button {{ stimulus_action('download_list', 'deleteDownload', 'click', {id: download.id}) }}>
|
||||||
|
<twig:ux:icon
|
||||||
|
name="ic:twotone-cancel" width="18px"
|
||||||
|
class="rounded-full align-middle text-red-600"
|
||||||
|
title="Remove {{ download.title }} from download list. This will not delete the file."
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
</turbo-stream>
|
</turbo-stream>
|
||||||
|
|||||||
85
templates/broadcast/Monitor.stream.html.twig
Normal file
85
templates/broadcast/Monitor.stream.html.twig
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{# Learn how to use Turbo Streams: https://github.com/symfony/ux-turbo#broadcast-doctrine-entities-update #}
|
||||||
|
{% block create %}
|
||||||
|
<turbo-stream action="remove" target="active_monitors_no_monitors">
|
||||||
|
</turbo-stream>
|
||||||
|
|
||||||
|
<turbo-stream action="append" target="monitors">
|
||||||
|
<template>
|
||||||
|
<tr id="monitor_{{ entity.id }}">
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-stone-800 min-w-[50ch] max-w-[50ch] truncate">
|
||||||
|
{{ entity.title }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800">
|
||||||
|
{{ entity.searchCount }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800">
|
||||||
|
{{ entity.createdAt|date('m/d/Y h:i a') }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800">
|
||||||
|
{{ entity.lastSearch|date('m/d/Y h:i a') }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800">
|
||||||
|
{% if entity.status == "New" %}
|
||||||
|
<twig:StatusBadge color="orange" status="{{ entity.status }}" />
|
||||||
|
{% elseif entity.status == "In Progress" or entity.status == "Active" %}
|
||||||
|
<twig:StatusBadge color="purple" status="{{ entity.status }}" />
|
||||||
|
{% else %}
|
||||||
|
<twig:StatusBadge color="green" status="{{ entity.status }}" />
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 flex flex-row align-middle justify-center">
|
||||||
|
<button {{ stimulus_action('monitor_list', 'deleteMonitor', 'click', {id: entity.id}) }}>
|
||||||
|
<twig:ux:icon
|
||||||
|
name="ic:twotone-cancel" width="18px"
|
||||||
|
class="rounded-full align-middle text-red-600"
|
||||||
|
title="Remove {{ entity.title }} from your Monitor list."
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
</turbo-stream>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block update %}
|
||||||
|
<turbo-stream action="prepend" target="monitors">
|
||||||
|
<template>
|
||||||
|
<tr id="monitor_{{ entity.id }}">
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-stone-800 min-w-[50ch] max-w-[50ch] truncate">
|
||||||
|
{{ entity.title }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800">
|
||||||
|
{{ entity.searchCount }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800">
|
||||||
|
{{ entity.createdAt|date('m/d/Y h:i a') }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800">
|
||||||
|
{{ entity.lastSearch|date('m/d/Y h:i a') }}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-800">
|
||||||
|
{% if entity.status == "New" %}
|
||||||
|
<twig:StatusBadge color="orange" status="{{ entity.status }}" />
|
||||||
|
{% elseif entity.status == "In Progress" or entity.status == "Active" %}
|
||||||
|
<twig:StatusBadge color="purple" status="{{ entity.status }}" />
|
||||||
|
{% else %}
|
||||||
|
<twig:StatusBadge color="green" status="{{ entity.status }}" />
|
||||||
|
{% endif %}
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 flex flex-row align-middle justify-center">
|
||||||
|
<button {{ stimulus_action('monitor_list', 'deleteMonitor', 'click', {id: entity.id}) }}>
|
||||||
|
<twig:ux:icon
|
||||||
|
name="ic:twotone-cancel" width="18px"
|
||||||
|
class="rounded-full align-middle text-red-600"
|
||||||
|
title="Remove {{ entity.title }} from your Monitor list."
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
</turbo-stream>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block remove %}
|
||||||
|
<turbo-stream action="remove" target="monitor_{{ id }}"></turbo-stream>
|
||||||
|
{% endblock %}
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
<twig:ux:icon
|
<twig:ux:icon
|
||||||
name="ic:twotone-cancel" width="18px"
|
name="ic:twotone-cancel" width="18px"
|
||||||
class="rounded-full align-middle text-red-600"
|
class="rounded-full align-middle text-red-600"
|
||||||
title="Remove {{ download.title }} from download list. This will not delete the file."
|
title="Remove {{ download.title }} from your Download list. This will not delete the file."
|
||||||
/>
|
/>
|
||||||
</button>
|
</button>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<div{{ attributes }} class="min-w-48">
|
<div{{ attributes.defaults(stimulus_controller('monitor_list')) }}>
|
||||||
<p class="text-white mb-1">The items you're currently monitoring to automatically download.</p>
|
<table id="monitor_list" class="divide-y divide-gray-200 bg-gray-50 overflow-hidden rounded-lg table-auto w-full" {{ turbo_stream_listen('App\\Monitor\\Framework\\Entity\\Monitor') }}>
|
||||||
<table id="downloads" class="divide-y divide-gray-200 bg-gray-50 overflow-hidden rounded-lg table-fixed" {{ turbo_stream_listen('App\\Download\\Framework\\Entity\\Download') }}>
|
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="bg-orange-500 bg-filter bg-blur-lg bg-opacity-80 text-gray-950">
|
<tr class="bg-orange-500 bg-filter bg-blur-lg bg-opacity-80 text-gray-950">
|
||||||
<th scope="col"
|
<th scope="col"
|
||||||
@@ -23,9 +22,10 @@
|
|||||||
class="px-6 py-3 text-start text-xs font-medium uppercase">
|
class="px-6 py-3 text-start text-xs font-medium uppercase">
|
||||||
Status
|
Status
|
||||||
</th>
|
</th>
|
||||||
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="divide-y divide-gray-50">
|
<tbody id="monitors" class="divide-y divide-gray-50">
|
||||||
{% if this.userMonitors.items|length > 0 %}
|
{% if this.userMonitors.items|length > 0 %}
|
||||||
{% for monitor in this.userMonitors.items %}
|
{% for monitor in this.userMonitors.items %}
|
||||||
<tr id="monitor_{{ monitor.id }}">
|
<tr id="monitor_{{ monitor.id }}">
|
||||||
@@ -50,18 +50,27 @@
|
|||||||
<twig:StatusBadge color="green" status="{{ monitor.status }}" />
|
<twig:StatusBadge color="green" status="{{ monitor.status }}" />
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
|
<td class="px-6 py-4 flex flex-row align-middle justify-center">
|
||||||
|
<button {{ stimulus_action('monitor_list', 'deleteMonitor', 'click', {id: monitor.id}) }}>
|
||||||
|
<twig:ux:icon
|
||||||
|
name="ic:twotone-cancel" width="18px"
|
||||||
|
class="rounded-full align-middle text-red-600"
|
||||||
|
title="Remove {{ monitor.title }} from your Monitor list."
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% if this.userMonitors.items|length > 5 %}
|
{% if this.userMonitors.items|length > 5 %}
|
||||||
<tr id="monitor_view_all">
|
<tr id="monitor_view_all">
|
||||||
<td colspan="5" class="py-2 whitespace-nowrap bg-orange-500 uppercase text-sm font-medium text-center text-white min-w-[50ch] max-w-[50ch] truncate">
|
<td colspan="100%" class="py-2 whitespace-nowrap bg-orange-500 uppercase text-sm font-medium text-center text-white min-w-[50ch] max-w-[50ch] truncate">
|
||||||
<a href="#">View All Monitors</a>
|
<a href="#">View All Monitors</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% else %}
|
{% else %}
|
||||||
<tr>
|
<tr id="active_monitors_no_monitors">
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-xs uppercase text-center col-span-2 font-medium text-stone-800" colspan="2">
|
<td class="px-6 py-4 whitespace-nowrap text-xs uppercase text-center col-span-2 font-medium text-stone-800" colspan="100%">
|
||||||
No monitors
|
No monitors
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user