mirror of
https://github.com/sigmasternchen/MyTube
synced 2025-03-15 04:48:55 +00:00
creating sets works now
added videos to sets is missing migration is missing
This commit is contained in:
parent
c10ad8aedc
commit
5607fed149
16 changed files with 787 additions and 14 deletions
|
@ -8,17 +8,3 @@
|
|||
font-weight: bold;
|
||||
color: lightgrey;
|
||||
}
|
||||
|
||||
.addButton {
|
||||
position: absolute;
|
||||
right: 2%;
|
||||
top: calc(90vh - 3vw);
|
||||
width: 3vw;
|
||||
}
|
||||
|
||||
.addButton button {
|
||||
position: fixed;
|
||||
height: 3vw;
|
||||
width: 3vw;
|
||||
font-size: 1.4vw;
|
||||
}
|
|
@ -70,3 +70,17 @@ a.btn.disabled {
|
|||
pointer-events: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.addButton {
|
||||
position: absolute;
|
||||
right: 2%;
|
||||
top: calc(90vh - 3vw);
|
||||
width: 3vw;
|
||||
}
|
||||
|
||||
.addButton button {
|
||||
position: fixed;
|
||||
height: 3vw;
|
||||
width: 3vw;
|
||||
font-size: 1.4vw;
|
||||
}
|
21
public/css/sets.css
Normal file
21
public/css/sets.css
Normal file
|
@ -0,0 +1,21 @@
|
|||
.rename {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.rename input[type=text] {
|
||||
width: 20%;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.rename button {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.videos .list img {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.list {
|
||||
max-height: 400px;
|
||||
overflow-y: scroll;
|
||||
}
|
24
public/js/search.js
Normal file
24
public/js/search.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
function search(input, elements, contents) {
|
||||
for (let i = 0; i < contents.length; i++) {
|
||||
console.log(contents[i])
|
||||
contents[i] = contents[i].toLowerCase();
|
||||
}
|
||||
|
||||
input.onkeyup = function () {
|
||||
let tokens = input.value;
|
||||
tokens = tokens.toLowerCase();
|
||||
tokens = tokens.split(" ");
|
||||
|
||||
for (let i = 0; i < contents.length; i++) {
|
||||
let okay = true;
|
||||
for (let j = 0; j < tokens.length; j++) {
|
||||
if (contents[i].indexOf(tokens[j]) < 0) {
|
||||
okay = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
elements[i].style.display = okay ? "block" : "none";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,13 +4,16 @@
|
|||
namespace App\Controller;
|
||||
|
||||
|
||||
use App\Entity\Set;
|
||||
use App\Entity\User;
|
||||
use App\Entity\Video;
|
||||
use App\Entity\VideoLink;
|
||||
use App\Form\SetType;
|
||||
use App\Form\VideoLinkType;
|
||||
use App\Form\VideoType;
|
||||
use App\Mapper\CustomUuidMapper;
|
||||
use App\Service\LoggingService;
|
||||
use App\Service\SetService;
|
||||
use App\Service\UserService;
|
||||
use App\Service\VideoLinkService;
|
||||
use App\Service\VideoService;
|
||||
|
@ -28,10 +31,13 @@ class DashboardController extends AbstractController
|
|||
{
|
||||
public const DELETE_VIDEO_CSRF_TOKEN_ID = "delete-video";
|
||||
public const DELETE_LINK_CSRF_TOKEN_ID = "delete-link";
|
||||
public const DELETE_SET_CSRF_TOKEN_ID = "delete-set";
|
||||
public const EDIT_SET_CSRF_TOKEN_ID = "edit-set";
|
||||
|
||||
private $userService;
|
||||
private $videoService;
|
||||
private $videoLinkService;
|
||||
private $setService;
|
||||
private $loggingService;
|
||||
|
||||
private $uuidMapper;
|
||||
|
@ -40,6 +46,7 @@ class DashboardController extends AbstractController
|
|||
UserService $userService,
|
||||
VideoService $videoService,
|
||||
VideoLinkService $videoLinkService,
|
||||
SetService $setService,
|
||||
LoggingService $loggingService,
|
||||
CustomUuidMapper $uuidMapper
|
||||
)
|
||||
|
@ -47,6 +54,7 @@ class DashboardController extends AbstractController
|
|||
$this->userService = $userService;
|
||||
$this->videoService = $videoService;
|
||||
$this->videoLinkService = $videoLinkService;
|
||||
$this->setService = $setService;
|
||||
$this->loggingService = $loggingService;
|
||||
$this->uuidMapper = $uuidMapper;
|
||||
}
|
||||
|
@ -375,4 +383,154 @@ class DashboardController extends AbstractController
|
|||
"form" => $form->createView()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/sets", name="app_sets")
|
||||
*/
|
||||
public function showSets(): Response
|
||||
{
|
||||
if (!$this->isGranted(User::ROLE_USER)) {
|
||||
// not logged in
|
||||
return $this->redirectToRoute("app_login");
|
||||
}
|
||||
|
||||
$user = $this->userService->getLoggedInUser();
|
||||
$sets = $this->setService->getAll($user);
|
||||
|
||||
foreach ($sets as $set) {
|
||||
$set->setCustomId($this->uuidMapper->toString($set->getId()));
|
||||
}
|
||||
|
||||
return $this->render("dashboard/sets.html.twig", [
|
||||
"sets" => $sets
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/sets/create", name="app_create_set")
|
||||
*/
|
||||
public function createSet(Request $request): Response
|
||||
{
|
||||
if (!$this->isGranted(User::ROLE_USER)) {
|
||||
// not logged in
|
||||
return $this->redirectToRoute("app_login");
|
||||
}
|
||||
|
||||
$set = new Set();
|
||||
$form = $this->createForm(SetType::class, $set);
|
||||
$form->handleRequest($request);
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$set = $form->getData();
|
||||
|
||||
$this->setService->add($set);
|
||||
|
||||
return $this->redirectToRoute("app_sets");
|
||||
}
|
||||
|
||||
return $this->render("dashboard/set-new.html.twig", [
|
||||
"form" => $form->createView()
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/sets/delete", name="app_delete_set", methods={"POST"})
|
||||
*/
|
||||
public function deleteSet(Request $request): Response
|
||||
{
|
||||
$token = $request->request->get("csrfToken");
|
||||
$setId = $request->request->get("setId");
|
||||
|
||||
if (!$this->isCsrfTokenValid(self::DELETE_SET_CSRF_TOKEN_ID, $token)) {
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
if (!$setId) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
try {
|
||||
$setId = $this->uuidMapper->fromString($setId);
|
||||
} catch (ConversionException $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
$set = $this->setService->get($setId);
|
||||
if ($set == null || $set->getCreator() != $this->userService->getLoggedInUser()) {
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
$this->setService->delete($set);
|
||||
|
||||
return $this->redirectToRoute("app_sets");
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/sets/{setId}", name="app_edit_set")
|
||||
*/
|
||||
public function editSet($setId, Request $request): Response
|
||||
{
|
||||
if (!$this->isGranted(User::ROLE_USER)) {
|
||||
// not logged in
|
||||
return $this->redirectToRoute("app_login");
|
||||
}
|
||||
|
||||
try {
|
||||
$setId = $this->uuidMapper->fromString($setId);
|
||||
} catch (ConversionException $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
$set = $this->setService->get($setId);
|
||||
|
||||
$form = $this->createForm(SetType::class, $set);
|
||||
$form->handleRequest($request);
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$set = $form->getData();
|
||||
|
||||
$this->setService->update($set);
|
||||
}
|
||||
|
||||
$set->setCustomId($this->uuidMapper->toString($set->getId()));
|
||||
|
||||
return $this->render("dashboard/set-edit.html.twig", [
|
||||
"form" => $form->createView(),
|
||||
"set" => $set
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/sets/{setId}/add", name="app_edit_set_add")
|
||||
*/
|
||||
public function editSetAdd($setId, Request $request): Response
|
||||
{
|
||||
if (!$this->isGranted(User::ROLE_USER)) {
|
||||
// not logged in
|
||||
return $this->redirectToRoute("app_login");
|
||||
}
|
||||
|
||||
try {
|
||||
$setId = $this->uuidMapper->fromString($setId);
|
||||
} catch (ConversionException $e) {
|
||||
throw new BadRequestHttpException();
|
||||
}
|
||||
|
||||
$set = $this->setService->get($setId);
|
||||
|
||||
$user = $this->userService->getLoggedInUser();
|
||||
|
||||
$videos = $this->videoService->getVideos($user);
|
||||
|
||||
$videos = array_udiff($videos, $set->getVideos()->getValues(), function ($a, $b) {
|
||||
return $a->getId()->compareTo($b->getId());
|
||||
});
|
||||
|
||||
foreach ($videos as $video) {
|
||||
$video->setCustomId($this->uuidMapper->toString($video->getId()));
|
||||
}
|
||||
|
||||
return $this->render("dashboard/set-edit-add.html.twig", [
|
||||
"set" => $set,
|
||||
"videos" => $videos
|
||||
]);
|
||||
}
|
||||
}
|
135
src/Entity/Set.php
Normal file
135
src/Entity/Set.php
Normal file
|
@ -0,0 +1,135 @@
|
|||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use App\Repository\SetRepository;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Ramsey\Uuid\Doctrine\UuidGenerator;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass=SetRepository::class)
|
||||
* @ORM\Table(name="`set`")
|
||||
*/
|
||||
class Set
|
||||
{
|
||||
/**
|
||||
* @ORM\Id
|
||||
* @ORM\Column(type="uuid", unique=true)
|
||||
* @ORM\GeneratedValue(strategy="CUSTOM")
|
||||
* @ORM\CustomIdGenerator(class=UuidGenerator::class)
|
||||
*/
|
||||
private $id;
|
||||
private $customId;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity=Video::class, inversedBy="sets")
|
||||
*/
|
||||
private $videos;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime_immutable")
|
||||
*/
|
||||
private $created;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=User::class)
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
*/
|
||||
private $creator;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->videos = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?UuidInterface
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Video[]
|
||||
*/
|
||||
public function getVideos(): Collection
|
||||
{
|
||||
return $this->videos;
|
||||
}
|
||||
|
||||
public function addVideo(Video $video): self
|
||||
{
|
||||
if (!$this->videos->contains($video)) {
|
||||
$this->videos[] = $video;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeVideo(Video $video): self
|
||||
{
|
||||
$this->videos->removeElement($video);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName(string $name): self
|
||||
{
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreated(): ?DateTimeImmutable
|
||||
{
|
||||
return $this->created;
|
||||
}
|
||||
|
||||
public function setCreated(): self
|
||||
{
|
||||
$this->created = new DateTimeImmutable();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreator(): ?User
|
||||
{
|
||||
return $this->creator;
|
||||
}
|
||||
|
||||
public function setCreator(?User $creator): self
|
||||
{
|
||||
$this->creator = $creator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCustomId(): string
|
||||
{
|
||||
return $this->customId;
|
||||
}
|
||||
|
||||
public function setCustomId($customId): self
|
||||
{
|
||||
$this->customId = $customId;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function clearVideos()
|
||||
{
|
||||
$this->videos = [];
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ namespace App\Entity;
|
|||
use App\Repository\VideoRepository;
|
||||
use DateTimeImmutable;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Ramsey\Uuid\Doctrine\UuidGenerator;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
@ -73,9 +74,15 @@ class Video
|
|||
|
||||
private $views = 0;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToMany(targetEntity=Set::class, mappedBy="videos")
|
||||
*/
|
||||
private $sets;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->videoLinks = new ArrayCollection();
|
||||
$this->sets = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?UuidInterface
|
||||
|
@ -243,4 +250,31 @@ class Video
|
|||
$this->views = $views;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Set[]
|
||||
*/
|
||||
public function getSets(): Collection
|
||||
{
|
||||
return $this->sets;
|
||||
}
|
||||
|
||||
public function addSet(Set $set): self
|
||||
{
|
||||
if (!$this->sets->contains($set)) {
|
||||
$this->sets[] = $set;
|
||||
$set->addVideo($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeSet(Set $set): self
|
||||
{
|
||||
if ($this->sets->removeElement($set)) {
|
||||
$set->removeVideo($this);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,11 @@ class VideoLink
|
|||
*/
|
||||
private $comment;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity=Set::class)
|
||||
*/
|
||||
private $sets;
|
||||
|
||||
public function getId(): ?UuidInterface
|
||||
{
|
||||
return $this->id;
|
||||
|
@ -207,4 +212,16 @@ class VideoLink
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getSets(): ?Set
|
||||
{
|
||||
return $this->sets;
|
||||
}
|
||||
|
||||
public function setSets(?Set $sets): self
|
||||
{
|
||||
$this->sets = $sets;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
32
src/Form/SetType.php
Normal file
32
src/Form/SetType.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
|
||||
use App\Entity\Set;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class SetType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, $options): void
|
||||
{
|
||||
$builder
|
||||
->add("name", TextType::class, [
|
||||
"required" => true
|
||||
])
|
||||
->add("submit", SubmitType::class);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
"data_class" => Set::class,
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
67
src/Repository/SetRepository.php
Normal file
67
src/Repository/SetRepository.php
Normal file
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Set;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method Set|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Set|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Set[] findAll()
|
||||
* @method Set[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class SetRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Set::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Set[] Returns an array of Set objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('s')
|
||||
->andWhere('s.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('s.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public function findOneBySomeField($value): ?Set
|
||||
{
|
||||
return $this->createQueryBuilder('s')
|
||||
->andWhere('s.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
public function save(Set $set)
|
||||
{
|
||||
$this->_em->persist($set);
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
public function delete(Set $set)
|
||||
{
|
||||
$this->_em->remove($set);
|
||||
$this->_em->flush();
|
||||
}
|
||||
|
||||
public function update($set)
|
||||
{
|
||||
$this->_em->flush();
|
||||
}
|
||||
}
|
57
src/Service/SetService.php
Normal file
57
src/Service/SetService.php
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
|
||||
use App\Entity\Set;
|
||||
use App\Entity\User;
|
||||
use App\Repository\SetRepository;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
class SetService
|
||||
{
|
||||
|
||||
private $userService;
|
||||
|
||||
private $setRepository;
|
||||
|
||||
public function __construct(
|
||||
UserService $userService,
|
||||
SetRepository $setRepository
|
||||
)
|
||||
{
|
||||
$this->userService = $userService;
|
||||
$this->setRepository = $setRepository;
|
||||
}
|
||||
|
||||
public function getAll(User $user): array
|
||||
{
|
||||
return $this->setRepository->findByCreator($user);
|
||||
}
|
||||
|
||||
public function add(Set $set)
|
||||
{
|
||||
$set->setCreated();
|
||||
$set->setCreator($this->userService->getLoggedInUser());
|
||||
$set->clearVideos();
|
||||
|
||||
$this->setRepository->save($set);
|
||||
}
|
||||
|
||||
public function get(UuidInterface $setId): ?Set
|
||||
{
|
||||
return $this->setRepository->findOneById($setId);
|
||||
}
|
||||
|
||||
public function delete(Set $set)
|
||||
{
|
||||
$this->setRepository->delete($set);
|
||||
}
|
||||
|
||||
public function update($set)
|
||||
{
|
||||
$this->setRepository->update($set);
|
||||
}
|
||||
|
||||
}
|
|
@ -48,6 +48,11 @@
|
|||
aria-current="page"
|
||||
href="{{ path("app_links") }}">Links</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link {% if route_name == "app_sets" %} active {% endif %}"
|
||||
aria-current="page"
|
||||
href="{{ path("app_sets") }}">Sets</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if is_granted('ROLE_ADMIN') %}
|
||||
<li class="nav-item">
|
||||
|
|
47
templates/dashboard/set-edit-add.html.twig
Normal file
47
templates/dashboard/set-edit-add.html.twig
Normal file
|
@ -0,0 +1,47 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Sets{% endblock %}
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="{{ asset("css/sets.css") }}">
|
||||
{% endblock %}
|
||||
{% block javascripts %}
|
||||
<script src="{{ asset("js/search.js") }}"></script>
|
||||
<script>
|
||||
(function () {
|
||||
let elements = document.getElementsByClassName("video");
|
||||
let contents = [];
|
||||
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
contents.push(elements[i].attributes["data-content"].textContent);
|
||||
}
|
||||
|
||||
search(document.getElementById("search-bar"), elements, contents);
|
||||
})();
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="bg-light shadow-5">
|
||||
<div class="videos">
|
||||
<div class="search">
|
||||
<input id="search-bar" type="text" placeholder="Search" class="form-control">
|
||||
</div>
|
||||
<div class="list">
|
||||
<ul>
|
||||
{% for video in videos %}
|
||||
<li class="video" data-content="{{ video.name }}">
|
||||
<a class="dropdown-item" href="#">
|
||||
<img alt="Thumbnail" src="{{ path("app_watch_thumbnail", {
|
||||
linkId: constant("App\\Controller\\WatchController::OWNER_LINK_ID"),
|
||||
videoId: video.customId
|
||||
}) }}"/>
|
||||
{{ video.name }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
<button
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
83
templates/dashboard/set-edit.html.twig
Normal file
83
templates/dashboard/set-edit.html.twig
Normal file
|
@ -0,0 +1,83 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Sets{% endblock %}
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="{{ asset("css/sets.css") }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<div class="bg-light shadow-5">
|
||||
<h2>Edit Set</h2>
|
||||
<div class="rename">
|
||||
{{ form_start(form) }}
|
||||
{{ form_widget(form.name) }}
|
||||
{{ form_widget(form.submit, { 'label': 'rename' }) }}
|
||||
{{ form_end(form) }}
|
||||
</div>
|
||||
<div>
|
||||
{% set editCsrfToken = csrf_token(constant("App\\Controller\\DashboardController::EDIT_SET_CSRF_TOKEN_ID")) %}
|
||||
<div class="links bg-light shadow-5">
|
||||
<table class="table table-hover">
|
||||
<tr>
|
||||
<td>#</td>
|
||||
<th>
|
||||
Video
|
||||
</th>
|
||||
<th>
|
||||
</th>
|
||||
</tr>
|
||||
{% for video in set.videos %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ loop.index }}
|
||||
</td>
|
||||
<td>
|
||||
<a href="{{ path("app_watch_page", {
|
||||
linkId: constant("App\\Controller\\WatchController::OWNER_LINK_ID"),
|
||||
videoId: video.customId
|
||||
}) }}">
|
||||
<img alt="Thumbnail" src="{{ path("app_watch_thumbnail", {
|
||||
linkId: constant("App\\Controller\\WatchController::OWNER_LINK_ID"),
|
||||
videoId: video.customId
|
||||
}) }}"/>
|
||||
{{ video.name }}
|
||||
</a>
|
||||
</td>
|
||||
<td class="no-wrap">
|
||||
<div class="btn-group" role="group">
|
||||
<form action="" method="POST">
|
||||
<input type="hidden" name="videoId" value="{{ video.customId }}">
|
||||
<input type="hidden" name="csrfToken" value="{{ editCsrfToken }}">
|
||||
<button class="btn btn-link dropdown-toggle deleteToggle" style="color: red;"
|
||||
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 this video from this set?<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>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="addButton">
|
||||
<a type="button" class="btn btn-primary btn-floating"
|
||||
href="{{ path("app_edit_set_add", {"setId": set.customId}) }}">
|
||||
<i class="fas fa-plus"></i>
|
||||
</a>
|
||||
</div>
|
||||
{% endblock %}
|
10
templates/dashboard/set-new.html.twig
Normal file
10
templates/dashboard/set-new.html.twig
Normal file
|
@ -0,0 +1,10 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Sets{% endblock %}
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="{{ asset("css/sets.css") }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{{ form(form) }}
|
||||
{% endblock %}
|
83
templates/dashboard/sets.html.twig
Normal file
83
templates/dashboard/sets.html.twig
Normal file
|
@ -0,0 +1,83 @@
|
|||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Sets{% endblock %}
|
||||
{% block stylesheets %}
|
||||
<link rel="stylesheet" href="{{ asset("css/sets.css") }}">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% if sets | length == 0 %}
|
||||
<div class="no-content">
|
||||
No sets yet.<br/>
|
||||
Go <a href="{{ path("app_create_set") }}">here</a> to add a new set.
|
||||
</div>
|
||||
{% else %}
|
||||
{% set deleteCsrfToken = csrf_token(constant("App\\Controller\\DashboardController::DELETE_SET_CSRF_TOKEN_ID")) %}
|
||||
<div class="bg-light shadow-5">
|
||||
<table class="table table-hover">
|
||||
<tr>
|
||||
<td></td>
|
||||
<th>
|
||||
Name
|
||||
</th>
|
||||
<th>
|
||||
Created
|
||||
</th>
|
||||
<th>
|
||||
# Videos
|
||||
</th>
|
||||
<th>
|
||||
</th>
|
||||
</tr>
|
||||
{% for set in sets %}
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
{{ set.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ set.created | date("Y-m-d") }}
|
||||
</td>
|
||||
<td>
|
||||
{{ set.videos | length }}
|
||||
</td>
|
||||
<td class="no-wrap">
|
||||
<div class="btn-group" role="group">
|
||||
<a class="btn btn-link" href="{{ path("app_edit_set", {"setId": set.customId}) }}">
|
||||
<i class="fas fa-cog"></i>
|
||||
</a>
|
||||
<form action="{{ path("app_delete_set") }}" method="POST">
|
||||
<input type="hidden" name="setId" value="{{ set.customId }}">
|
||||
<input type="hidden" name="csrfToken" value="{{ deleteCsrfToken }}">
|
||||
<button class="btn btn-link dropdown-toggle deleteToggle" style="color: red;"
|
||||
id="{{ set.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="{{ set.customId }}-deleteDropDownMenu"
|
||||
aria-labelledby="{{ set.customId }}-deleteDropDown">
|
||||
Do you really want to delete this set?<br/>
|
||||
<button class="btn btn-link deleteButton">YES</button>
|
||||
<button class="btn btn-primary" onclick="removeClass('show', [
|
||||
'#{{ set.customId }}-deleteDropDown',
|
||||
'#{{ set.customId }}-deleteDropDownMenu'
|
||||
]); return false;">NO
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</div>
|
||||
<div class="addButton">
|
||||
<a type="button" class="btn btn-primary btn-floating" href="{{ path("app_create_set") }}">
|
||||
<i class="fas fa-plus"></i>
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
Loading…
Reference in a new issue