upload progress in dashboard

This commit is contained in:
overflowerror 2021-01-07 19:59:37 +01:00
parent 07f9827ed2
commit d6197a692a
6 changed files with 135 additions and 12 deletions

View file

@ -95,4 +95,26 @@
.link:hover a { .link:hover a {
color: grey; color: grey;
}
.transcodingProgress {
position: absolute;
width: 100%;
height: 100%;
bottom: 0;
}
.transcodingProgress .value {
width: 100%;
color: lightgrey;
text-align: center;
position: absolute;
bottom: 5%;
}
.transcodingProgress .bar {
position: absolute;
bottom: 0;
height: 2%;
background-color: lightgrey;
} }

21
public/js/ajax.js Normal file
View file

@ -0,0 +1,21 @@
function ajaxGet(url, callback) {
var http = new XMLHttpRequest();
http.open("GET", url, true);
http.onreadystatechange = function () {
if (http.readyState === 4) {
callback(http.responseText);
}
}
http.send(null);
}
function ajaxPost(url, data, callback) {
var http = new XMLHttpRequest();
http.open("POST", url, true);
http.onreadystatechange = function () {
if (http.readyState === 4) {
callback(http.responseText);
}
}
http.send(data);
}

View file

@ -15,8 +15,11 @@ use App\Service\VideoService;
use Doctrine\DBAL\Types\ConversionException; use Doctrine\DBAL\Types\ConversionException;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
class DashboardController extends AbstractController class DashboardController extends AbstractController
@ -94,6 +97,36 @@ class DashboardController extends AbstractController
]); ]);
} }
/**
* @Route("/upload/{videoId}", name="app_upload_status")
*/
public function uploadStatus($videoId): Response
{
if (!$this->isGranted("ROLE_USER")) {
// not logged in
return $this->redirectToRoute("app_login");
}
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();
}
return new JsonResponse([
"id" => $this->uuidMapper->toString($video->getId()),
"state" => $video->getStateString(),
"stateId" => $video->getState(),
"progress" => $video->getTranscodingProgress()
]);
}
/** /**
* @Route("/links", name="app_links") * @Route("/links", name="app_links")
*/ */

View file

@ -73,9 +73,9 @@ class Video
private $length; private $length;
/** /**
* @ORM\Column(type="integer", nullable=true) * @ORM\Column(type="integer")
*/ */
private $transcodingProgress; private $transcodingProgress = 0;
public function __construct() public function __construct()
{ {

View file

@ -70,6 +70,7 @@
<script src="{{ asset("js/mdb.min.js") }}"></script> <script src="{{ asset("js/mdb.min.js") }}"></script>
<script src="{{ asset("js/clipboard.js") }}"></script> <script src="{{ asset("js/clipboard.js") }}"></script>
<script src="{{ asset("js/toasts.js") }}"></script> <script src="{{ asset("js/toasts.js") }}"></script>
<script src="{{ asset("js/ajax.js") }}"></script>
{% block javascripts %}{% endblock %} {% block javascripts %}{% endblock %}
</body> </body>
</html> </html>

View file

@ -5,26 +5,63 @@
<link rel="stylesheet" href="{{ asset("css/dashboard.css") }}"> <link rel="stylesheet" href="{{ asset("css/dashboard.css") }}">
{% endblock %} {% endblock %}
{% block javascripts %}
<script>
(function () {
let intervalIds = [];
for (let id in autoupdate) {
intervalIds[id] = setInterval(function () {
ajaxGet(autoupdate[id], function (data) {
data = JSON.parse(data);
let element = document.getElementById("video-" + id);
if (data.stateId === {{ constant("App\\Entity\\Video::DONE") }}) {
element.getElementsByClassName("disable")[0].remove();
clearInterval(intervalIds[id]);
} else {
if (data.stateId > {{ constant("App\\Entity\\Video::PROCESSING_THUMBNAIL") }}) {
let image = element.getElementsByClassName("thumbnail")[0].getElementsByTagName("img")[0];
if (image.hasAttribute("data-src")) {
image.src = image.getAttribute("data-src");
}
}
element.getElementsByClassName("state")[0].innerText = data.state;
let progress = element.getElementsByClassName("transcodingProgress")[0];
progress.getElementsByClassName("value")[0].innerText = data.progress + " %";
progress.getElementsByClassName("bar")[0].style.width = data.progress + "%";
}
});
}, 2000);
}
})();
</script>
{% endblock %}
{% block body %} {% block body %}
<div class="grid-container"> <div class="grid-container">
<script>var autoupdate = [];</script>
<div class="row"> <div class="row">
{% for video in videos %} {% for video in videos %}
{% set disabled = video.state != constant("App\\Entity\\Video::DONE") %} {% set disabled = video.state != constant("App\\Entity\\Video::DONE") %}
<div class="video-tile col-md-4"> <div class="video-tile col-md-4" id="video-{{ video.customId }}">
<div class="tile-content bg-light shadow-5-strong"> <div class="tile-content bg-light shadow-5-strong">
<div class="thumbnail" onclick="location.href = '{{ path("app_watch_page", { <div class="thumbnail" onclick="location.href = '{{ path("app_watch_page", {
linkId: constant("App\\Controller\\WatchController::OWNER_LINK_ID"), linkId: constant("App\\Controller\\WatchController::OWNER_LINK_ID"),
videoId: video.customId videoId: video.customId
}) }}'"> }) }}'">
{% if disabled == false %} <img alt="Thumbnail"
<img alt="Thumbnail" src="{{ path("app_watch_thumbnail", { {{ video.state > constant("App\\Entity\\Video::PROCESSING_THUMBNAIL") ? "src" : "data-src" }}
linkId: constant("App\\Controller\\WatchController::OWNER_LINK_ID"), ="{{ path("app_watch_thumbnail", {
videoId: video.customId linkId: constant("App\\Controller\\WatchController::OWNER_LINK_ID"),
}) }}"/> videoId: video.customId
<div class="play-button"> }) }}"/>
<i class="fas fa-play"></i> <div class="play-button">
</div> <i class="fas fa-play"></i>
{% endif %} </div>
</div> </div>
<div class="info"> <div class="info">
<div class="link"> <div class="link">
@ -38,6 +75,11 @@
</p> </p>
</div> </div>
{% if disabled %} {% if disabled %}
<script>
autoupdate["{{ video.customId }}"] = "{{ path("app_upload_status", {
videoId: video.customId
}) }}";
</script>
<div class="disable"> <div class="disable">
<div class="spinner spinner-border" role="status"> <div class="spinner spinner-border" role="status">
<span class="visually-hidden">Loading...</span> <span class="visually-hidden">Loading...</span>
@ -45,6 +87,10 @@
<div class="state"> <div class="state">
{{ video.getStateString() }} {{ video.getStateString() }}
</div> </div>
<div class="transcodingProgress">
<div class="value">{{ video.transcodingProgress }} %</div>
<div class="bar" style="width: {{ video.transcodingProgress }}%;"></div>
</div>
</div> </div>
{% endif %} {% endif %}
</div> </div>