diff --git a/public/asset/default/css/common.css b/public/asset/default/css/common.css index eec5496..5d4291a 100644 --- a/public/asset/default/css/common.css +++ b/public/asset/default/css/common.css @@ -3,6 +3,18 @@ margin: 0; padding: 0; box-sizing: border-box; + outline: none; +} + +:focus, +:focus-within, +:focus-visible, +:active, +:target, +:hover { + opacity: 1; + transition: opacity .2s ease-in-out; + } body { @@ -20,11 +32,6 @@ a:active { opacity: .9; } -a:hover { - opacity: 1; - transition: opacity .5s ease-in-out; -} - h1, h2, h3, h4, h5 { display: inline-block; font-weight: normal; @@ -39,15 +46,8 @@ h2 { font-size: 16px; } -a h2, -a:visited h2, -a:active h2 { - /* @TODO doubts - color: #a4d4ff; - */ -} - input, +button, select, textarea { accent-color: #65916d; @@ -56,18 +56,19 @@ textarea { color: #ccc; border-radius: 3px; padding: 8px; + opacity: .96; } textarea:focus, input:focus { border: #65916d 1px solid; - outline: none; color: #fff; } select[multiple="multiple"] > option { border-top: 1px #5d627d solid; border-bottom: 1px #5d627d solid; + color: #fff; } select[multiple="multiple"] > option:active, @@ -77,34 +78,41 @@ select[multiple="multiple"] > option:checked { border-top: 1px #65916d solid; border-bottom: 1px #65916d solid; background: linear-gradient(#65916d, #65916d); - outline: none; - color: #fff; } +button, +input[type="submit"] { + cursor: pointer; +} + +/* +button, +input[type="submit"] { + cursor: pointer; + background: #65916d; + border-radius: 3px; + padding: 8px; + color: #fff +} +*/ + textarea, select[multiple="multiple"] { min-height: 180px; } + textarea::placeholder, input::placeholder { color: #9698a5; opacity: 1; } -input:hover, +input[type="text"]:hover, textarea:hover { background: #636884; } -input[type="submit"] { - cursor: pointer; -} - -ul { - list-style: none; -} - td { padding: 2px 0; } @@ -116,17 +124,4 @@ header a.logo { header a.logo > span { color: #96d9a1; -} - -a.button, -a.button:visited, -a.button:active, -a.button:hover, -.button { - background: #5d627d; - color: #ccc; - border: 0; - border-radius: 3px; - padding: 6px 8px; - font-size: 13px; } \ No newline at end of file diff --git a/public/asset/default/css/framework.css b/public/asset/default/css/framework.css index ebfb3bc..d928ccc 100644 --- a/public/asset/default/css/framework.css +++ b/public/asset/default/css/framework.css @@ -188,6 +188,10 @@ a.label-green:hover { background-color: #34384f; } +.background-color-night-light { + background-color: #3d4159; +} + .background-color-green { background-color: #65916d; } @@ -325,6 +329,11 @@ a:visited.background-color-hover-night-light:hover { padding: 24px; } +.padding-x-24-px { + padding-left: 24px; + padding-right: 24px; +} + .margin-l-4-px { margin-left: 4px; } diff --git a/src/Controller/TorrentController.php b/src/Controller/TorrentController.php index dc12c5a..913180f 100644 --- a/src/Controller/TorrentController.php +++ b/src/Controller/TorrentController.php @@ -11,16 +11,15 @@ use Symfony\Component\HttpFoundation\Request; use App\Service\UserService; use App\Service\TorrentService; -use App\Service\TimeService; class TorrentController extends AbstractController { #[Route( - '/{_locale}/torrent/{id}', + '/{_locale}/torrent/{torrentId}', name: 'torrent_info', requirements: [ - 'id' => '\d+' + 'torrentId' => '\d+' ], methods: [ @@ -32,7 +31,6 @@ class TorrentController extends AbstractController TranslatorInterface $translator, UserService $userService, TorrentService $torrentService, - TimeService $timeService ): Response { // Init user @@ -41,7 +39,7 @@ class TorrentController extends AbstractController ); // Init torrent - if (!$torrent = $torrentService->getTorrent($request->get('id'))) + if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) { throw $this->createNotFoundException(); } @@ -62,18 +60,18 @@ class TorrentController extends AbstractController } /* - if (!$torrent = $torrentService->getTorrentLocales($request->get('id'))) + if (!$torrent = $torrentService->getTorrentLocales($request->get('torrentId'))) { throw $this->createNotFoundException(); } */ -//print_r($file->getFileTree());exit; + return $this->render('default/torrent/info.html.twig', [ 'torrent' => [ 'id' => $torrent->getId(), 'added' => 0, // @TODO - 'locales' => [], //$torrent->getLocales(), + 'locales' => $torrentService->findLastTorrentLocales($torrent->getId()), 'pages' => [] ], 'file' => @@ -101,6 +99,184 @@ class TorrentController extends AbstractController ]); } + #[Route( + '/{_locale}/torrent/{torrentId}/edit/locales/{torrentLocalesId}', + name: 'torrent_edit_locales', + requirements: + [ + 'torrentId' => '\d+', + 'torrentLocalesId' => '\d+', + ], + defaults: + [ + 'torrentLocalesId' => null, + ], + methods: + [ + 'GET', + 'POST' + ] + )] + + public function editLocales( + Request $request, + TranslatorInterface $translator, + UserService $userService, + TorrentService $torrentService + ): Response + { + // Init user + $user = $userService->init( + $request->getClientIp() + ); + + if (!$user->isStatus()) + { + // @TODO + throw new \Exception( + $translator->trans('Access denied') + ); + } + + // Init torrent + if (!$torrent = $torrentService->getTorrent($request->get('torrentId'))) + { + throw $this->createNotFoundException(); + } + + // Init torrent locales + $torrentLocalesValue = []; + + // Get from edition version requested + if ($request->get('torrentLocalesId')) + { + if ($torrentLocales = $torrentService->getTorrentLocales($request->get('torrentLocalesId'))) + { + foreach ($torrentLocales->getValue() as $value) + { + $torrentLocalesValue[] = $value; + } + } + + else + { + throw $this->createNotFoundException(); + } + } + + // Otherwise, get latest available + else + { + if ($torrentLocales = $torrentService->findLastTorrentLocales($torrent->getId())) + { + foreach ($torrentLocales->getValue() as $value) + { + $torrentLocalesValue[] = $value; + } + + // Update active locale + $request->attributes->set('torrentLocalesId', $torrentLocales->getId()); + } + + else + { + $torrentLocalesValue[] = $request->get('_locale'); + } + } + + // Init edition history + $editions = []; + foreach ($torrentService->findTorrentLocales($torrent->getId()) as $torrentLocales) + { + $editions[] = + [ + 'id' => $torrentLocales->getId(), + 'added' => $torrentLocales->getAdded(), + 'approved' => $torrentLocales->isApproved(), + 'active' => $torrentLocales->getId() == $request->get('torrentLocalesId'), + 'user' => + [ + 'id' => $torrentLocales->getUserId(), + 'identicon' => $userService->identicon( + $userService->get( + $torrentLocales->getUserId() + )->getAddress() + ), + ] + ]; + } + + // Init form + $form = + [ + 'locales' => + [ + 'error' => [], + 'attribute' => + [ + 'value' => $request->get('locales') ? $request->get('locales') : $torrentLocalesValue, + 'placeholder' => $translator->trans('Content language') + ] + ] + ]; + + // Process request + if ($request->isMethod('post')) + { + /// Locales + $locales = []; + if ($request->get('locales')) + { + foreach ((array) $request->get('locales') as $locale) + { + if (in_array($locale, explode('|', $this->getParameter('app.locales')))) + { + $locales[] = $locale; + } + } + } + + //// At least one valid locale required + if (!$locales) + { + $form['locales']['error'][] = $translator->trans('At least one locale required'); + } + + // Request is valid + if (empty($form['locales']['error'])) + { + // Save data + $torrentService->addTorrentLocales( + $torrent->getId(), + $user->getId(), + time(), + $locales, + $user->isApproved() + ); + + // Redirect to info page created + return $this->redirectToRoute( + 'torrent_info', + [ + '_locale' => $request->get('_locale'), + 'torrentId' => $torrent->getId() + ] + ); + } + } + + // Render form template + return $this->render( + 'default/torrent/edit/locales.html.twig', + [ + 'torrentId' => $torrent->getId(), + 'locales' => explode('|', $this->getParameter('app.locales')), + 'editions' => $editions, + 'form' => $form, + ] + ); + } + #[Route( '/{_locale}/submit/torrent', name: 'torrent_submit', @@ -208,7 +384,7 @@ class TorrentController extends AbstractController if (empty($form['torrent']['error']) && empty($form['locales']['error'])) { // Save data - $torrent = $torrentService->submit( + $torrent = $torrentService->add( $file->getPathName(), $user->getId(), time(), @@ -221,8 +397,8 @@ class TorrentController extends AbstractController return $this->redirectToRoute( 'torrent_info', [ - '_locale' => $request->get('_locale'), - 'id' => $torrent->getId() + '_locale' => $request->get('_locale'), + 'torrentId' => $torrent->getId() ] ); } diff --git a/src/Repository/TorrentLocalesRepository.php b/src/Repository/TorrentLocalesRepository.php index 8ba7b73..4cc44a0 100644 --- a/src/Repository/TorrentLocalesRepository.php +++ b/src/Repository/TorrentLocalesRepository.php @@ -20,4 +20,37 @@ class TorrentLocalesRepository extends ServiceEntityRepository { parent::__construct($registry, TorrentLocales::class); } + + public function getTorrentLocales(int $id): ?TorrentLocales + { + return $this->createQueryBuilder('tl') + ->where('tl.id = :id') + ->setParameter('id', $id) + ->getQuery() + ->getOneOrNullResult() + ; + } + + public function findLastTorrentLocales(int $torrentId): ?TorrentLocales + { + return $this->createQueryBuilder('tl') + ->where('tl.torrentId = :torrentId') + ->setParameter('torrentId', $torrentId) + ->orderBy('tl.id', 'DESC') // same to tl.added + ->setMaxResults(1) + ->getQuery() + ->getOneOrNullResult() + ; + } + + public function findTorrentLocales(int $torrentId): array + { + return $this->createQueryBuilder('tl') + ->where('tl.torrentId = :torrentId') + ->setParameter('torrentId', $torrentId) + ->orderBy('tl.id', 'DESC') // same to tl.added + ->getQuery() + ->getResult() + ; + } } diff --git a/src/Service/TorrentService.php b/src/Service/TorrentService.php index c9ec05d..6f1a94c 100644 --- a/src/Service/TorrentService.php +++ b/src/Service/TorrentService.php @@ -69,7 +69,28 @@ class TorrentService ->findOneByIdField($id); } - public function submit( + public function getTorrentLocales(int $id): ?TorrentLocales + { + return $this->entityManagerInterface + ->getRepository(TorrentLocales::class) + ->getTorrentLocales($id); + } + + public function findLastTorrentLocales(int $torrentId): ?TorrentLocales + { + return $this->entityManagerInterface + ->getRepository(TorrentLocales::class) + ->findLastTorrentLocales($torrentId); + } + + public function findTorrentLocales(int $torrentId): array + { + return $this->entityManagerInterface + ->getRepository(TorrentLocales::class) + ->findTorrentLocales($torrentId); + } + + public function add( string $filepath, int $userId, int $added, @@ -78,7 +99,7 @@ class TorrentService bool $approved ): ?Torrent { - $torrent = $this->saveTorrent( + $torrent = $this->addTorrent( $this->getTorrentInfoNameByFilepath($filepath), $this->getTorrentKeywordsByFilepath($filepath) ); @@ -93,7 +114,7 @@ class TorrentService if (!empty($locales)) { - $this->saveTorrentLocales( + $this->addTorrentLocales( $torrent->getId(), $userId, $added, @@ -102,7 +123,7 @@ class TorrentService ); } - $this->saveTorrentSensitive( + $this->addTorrentSensitive( $torrent->getId(), $userId, $added, @@ -113,7 +134,7 @@ class TorrentService return $torrent; } - public function saveTorrent( + public function addTorrent( string $filepath, string $keywords ): ?Torrent @@ -129,7 +150,7 @@ class TorrentService return $torrent; } - public function saveTorrentLocales( + public function addTorrentLocales( int $torrentId, int $userId, int $added, @@ -151,7 +172,7 @@ class TorrentService return $torrentLocales; } - public function saveTorrentSensitive( + public function addTorrentSensitive( int $torrentId, int $userId, int $added, diff --git a/templates/default/torrent/edit/locales.html.twig b/templates/default/torrent/edit/locales.html.twig new file mode 100644 index 0000000..4c1b543 --- /dev/null +++ b/templates/default/torrent/edit/locales.html.twig @@ -0,0 +1,85 @@ +{% extends 'default/layout.html.twig' %} +{% block title %}{{'Edit torrent locales'|trans }} - {{ name }}{% endblock %} +{% block main_content %} +
- {{ 'Name'|trans }} - | -|||||||||||||||||||
- {{ file.name }} - | -|||||||||||||||||||
- {{ 'Created'|trans }} - | -|||||||||||||||||||
- {{ file.created | format_date }} - | -|||||||||||||||||||
- {{ 'Info hash v1'|trans }} - | -|||||||||||||||||||
- {{ file.hash.v1 }} - | -|||||||||||||||||||
- {{ 'Info hash v2'|trans }} - | -|||||||||||||||||||
- {{ file.hash.v2 }} - | -|||||||||||||||||||
- {{ 'Generated'|trans }} - | -|||||||||||||||||||
- {{ file['created by'] }} - | -|||||||||||||||||||
- {{ 'Comment'|trans }} - | -|||||||||||||||||||
- {{ file.comment }} - | -|||||||||||||||||||
- {{ 'Files'|trans }} - | -|||||||||||||||||||
- {{ recursive_file_tree(tree) }} - | -|||||||||||||||||||
- {{ 'Trackers'|trans }} - | -|||||||||||||||||||
- | |||||||||||||||||||
+
+ {{ 'Common'|trans }}
+
+
+
+
+ {{ 'Files'|trans }}
+
+
+ {% for tree in file.tree %}
+ {{ recursive_file_tree(tree) }}
+ {% endfor %}
+
+
+ {{ 'Trackers'|trans }}
+
+
+ {% for tracker in trackers %}
+
+ {{ tracker }}
+
+ {% endfor %}
+ {% for announces in trackers %}
+ {% for tracker in announces %}
+
+ {% if tracker not in trackers %}
{{ tracker }}
- |
- |||||||||||||||||||
- {{ file.announce }} - | -- {% if file.announce not in trackers %} - + - + {% endif %} - | -||||||||||||||||||
- {{ tracker }} - | -- {% if tracker not in trackers %} - - - - {% endif %} - | -||||||||||||||||||
- | |||||||||||||||||||
- {{ 'Locales'|trans }} - | -|||||||||||||||||||
- | |||||||||||||||||||
- - {{'Edit'|trans }} - - | -|||||||||||||||||||
- - {{'Add'|trans }} - - | -|||||||||||||||||||
- | |||||||||||||||||||
- {{ 'Pages'|trans }} - | -|||||||||||||||||||
- | |||||||||||||||||||
- - {{'Edit'|trans }} - - | -|||||||||||||||||||
- - {{'Add'|trans }} - - | -