mirror of
https://github.com/sigmasternchen/MyTube
synced 2025-03-15 04:48:55 +00:00
video deletion now works
This commit is contained in:
parent
7ec2db7d77
commit
de2e13f6e6
9 changed files with 108 additions and 14 deletions
|
@ -18,12 +18,6 @@
|
|||
height: 30px;
|
||||
}
|
||||
|
||||
.avatar-dropdown {
|
||||
/*top: calc(100% + 0.40rem);
|
||||
right: -0.75rem;*/
|
||||
left: auto !important;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
}
|
|
@ -138,4 +138,19 @@
|
|||
|
||||
.no-content {
|
||||
margin-left: 3%;
|
||||
}
|
||||
|
||||
.deleteToggle:after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.deleteConfirm {
|
||||
text-align: center;
|
||||
padding: 1vw;
|
||||
font-size: 1vw;
|
||||
min-width: 14vw;
|
||||
}
|
||||
|
||||
.deleteButton {
|
||||
color: red;
|
||||
}
|
11
public/js/utils.js
Normal file
11
public/js/utils.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
function removeClass(className, elements) {
|
||||
if (typeof elements == "string") {
|
||||
elements = [elements];
|
||||
}
|
||||
|
||||
for (let i in elements) {
|
||||
let element = elements[i];
|
||||
element = document.querySelector(element);
|
||||
element.className = element.className.replaceAll(className, "");
|
||||
}
|
||||
}
|
|
@ -25,6 +25,8 @@ use Symfony\Component\Routing\Annotation\Route;
|
|||
|
||||
class DashboardController extends AbstractController
|
||||
{
|
||||
public const DELETE_VIDEO_CSRF_TOKEN_ID = "delete-video";
|
||||
|
||||
private $userService;
|
||||
private $videoService;
|
||||
private $videoLinkService;
|
||||
|
@ -102,6 +104,38 @@ class DashboardController extends AbstractController
|
|||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/video/delete", name="app_video_delete", methods={"POST"})
|
||||
*/
|
||||
public function delete(Request $request): Response
|
||||
{
|
||||
$token = $request->request->get("csrfToken");
|
||||
$videoId = $request->request->get("videoId");
|
||||
|
||||
if (!$this->isCsrfTokenValid(self::DELETE_VIDEO_CSRF_TOKEN_ID, $token)) {
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
if (!$videoId) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
try {
|
||||
$videoId = $this->uuidMapper->fromString($videoId);
|
||||
} catch (ConversionException $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
$video = $this->videoService->get($videoId);
|
||||
if ($video == null || $video->getUploader() != $this->userService->getLoggedInUser()) {
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
$this->videoService->delete($video);
|
||||
|
||||
return $this->redirectToRoute("app_dashboard");
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/upload/{videoId}", name="app_upload_status")
|
||||
*/
|
||||
|
|
|
@ -12,11 +12,15 @@ use Ramsey\Uuid\UuidInterface;
|
|||
class CustomUuidMapper
|
||||
{
|
||||
private const REPLACE_SLASH = "-";
|
||||
private const REPLACE_PLUS = "_";
|
||||
|
||||
public function fromString($str): UuidInterface
|
||||
{
|
||||
try {
|
||||
return Uuid::fromBytes(base64_decode(str_replace(self::REPLACE_SLASH, "/", $str) . "=="));
|
||||
return Uuid::fromBytes(
|
||||
base64_decode(
|
||||
str_replace(self::REPLACE_PLUS, "+",
|
||||
str_replace(self::REPLACE_SLASH, "/", $str) . "==")));
|
||||
} catch (InvalidArgumentException $e) {
|
||||
throw new ConversionException($e);
|
||||
}
|
||||
|
@ -24,6 +28,10 @@ class CustomUuidMapper
|
|||
|
||||
public function toString(UuidInterface $uuid): string
|
||||
{
|
||||
return str_replace("/", self::REPLACE_SLASH, str_replace("==", "", base64_encode($uuid->getBytes())));
|
||||
return
|
||||
str_replace("+", self::REPLACE_PLUS,
|
||||
str_replace("/", self::REPLACE_SLASH,
|
||||
str_replace("==", "",
|
||||
base64_encode($uuid->getBytes()))));
|
||||
}
|
||||
}
|
|
@ -56,4 +56,10 @@ class VideoRepository extends ServiceEntityRepository
|
|||
{
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
public function delete(Video $video)
|
||||
{
|
||||
$this->_em->remove($video);
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,4 +52,9 @@ class VideoService
|
|||
{
|
||||
return $this->videoRepository->findOneById($videoId);
|
||||
}
|
||||
|
||||
public function delete(Video $video)
|
||||
{
|
||||
$this->videoRepository->delete($video);
|
||||
}
|
||||
}
|
|
@ -75,7 +75,8 @@
|
|||
alt=""
|
||||
/>
|
||||
</a>
|
||||
<ul class="dropdown-menu avatar-dropdown" aria-labelledby="navbarDropdownMenuLink">
|
||||
<ul class="dropdown-menu dropdown-menu-end avatar-dropdown"
|
||||
aria-labelledby="navbarDropdownMenuLink">
|
||||
<li><a class="dropdown-item" href="#">My profile</a></li>
|
||||
<li><a class="dropdown-item" href="#">Settings</a></li>
|
||||
<li><a class="dropdown-item" href="{{ path("app_logout") }}">Logout</a></li>
|
||||
|
@ -92,6 +93,7 @@
|
|||
<script src="{{ asset("js/clipboard.js") }}"></script>
|
||||
<script src="{{ asset("js/toasts.js") }}"></script>
|
||||
<script src="{{ asset("js/ajax.js") }}"></script>
|
||||
<script src="{{ asset("js/utils.js") }}"></script>
|
||||
{% block javascripts %}{% endblock %}
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% set deleteCsrfToken = csrf_token(constant("App\\Controller\\DashboardController::DELETE_VIDEO_CSRF_TOKEN_ID")) %}
|
||||
<div class="grid-container">
|
||||
<script>var autoupdate = [];</script>
|
||||
<div class="row">
|
||||
|
@ -66,17 +67,35 @@
|
|||
<div class="info">
|
||||
<div class="buttons btn-group btn-group-sm">
|
||||
<button class="btn btn-primary"
|
||||
onclick="location.href='{{ path("app_new_link") }}?video={{ video.customId | url_encode }}'">
|
||||
onclick="location.href='{{ path("app_new_link") }}?video={{ video.customId }}'">
|
||||
<i class="fas fa-link"></i>
|
||||
</button>
|
||||
<button class="btn btn-primary"
|
||||
onclick="">
|
||||
<i class="fas fa-cog"></i>
|
||||
</button>
|
||||
<button class="btn btn-primary btn-danger"
|
||||
onclick="">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
<form action="{{ path("app_video_delete") }}" method="POST">
|
||||
<input type="hidden" name="videoId" value="{{ video.customId }}">
|
||||
<input type="hidden" name="csrfToken" value="{{ deleteCsrfToken }}">
|
||||
<button class="btn btn-primary btn-danger dropdown-toggle deleteToggle"
|
||||
id="{{ video.customId }}-deleteDropDown"
|
||||
data-mdb-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
onclick="">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu dropdown-menu-end deleteConfirm"
|
||||
id="{{ video.customId }}-deleteDropDownMenu"
|
||||
aria-labelledby="{{ video.customId }}-deleteDropDown">
|
||||
Do you really want to delete "{{ video.name }}"?<br/>
|
||||
<button class="btn btn-link deleteButton">YES</button>
|
||||
<button class="btn btn-primary" onclick="removeClass('show', [
|
||||
'#{{ video.customId }}-deleteDropDown',
|
||||
'#{{ video.customId }}-deleteDropDownMenu'
|
||||
]); return false;">NO
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<h5>{{ video.name }}</h5>
|
||||
<div class="views">
|
||||
|
|
Loading…
Reference in a new issue