Added cancel upload button

Added button delete
This commit is contained in:
Sergio Brighenti 2019-11-21 15:23:02 +01:00
parent 8730a42ad5
commit 7589348daf
9 changed files with 167 additions and 145 deletions

View file

@ -4,6 +4,7 @@
+ Added ability to add custom HTML in \<head\> tag.
+ Added ability to show a preview of PDF files.
+ Added remember me functionality.
+ Added delete button on the preview page if the user is logged in.
+ Raw URL now accept file extensions.
+ The linux script can be used on headless systems.
+ Improved installer.

View file

@ -16,19 +16,19 @@ use Slim\Exception\HttpUnauthorizedException;
class MediaController extends Controller
{
/**
* @param Request $request
* @param Response $response
* @param string $userCode
* @param string $mediaCode
* @param string|null $token
* @param Request $request
* @param Response $response
* @param string $userCode
* @param string $mediaCode
* @param string|null $token
*
* @return Response
* @throws HttpNotFoundException
* @throws \Twig\Error\LoaderError
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
* @throws FileNotFoundException
*
* @return Response
*/
public function show(Request $request, Response $response, string $userCode, string $mediaCode, string $token = null): Response
{
@ -42,47 +42,47 @@ class MediaController extends Controller
if (isBot($request->getHeaderLine('User-Agent'))) {
return $this->streamMedia($request, $response, $filesystem, $media);
} else {
try {
$media->mimetype = $filesystem->getMimetype($media->storage_path);
$size = $filesystem->getSize($media->storage_path);
}
$type = explode('/', $media->mimetype)[0];
if ($type === 'image' && !isDisplayableImage($media->mimetype)) {
try {
$media->mimetype = $filesystem->getMimetype($media->storage_path);
$size = $filesystem->getSize($media->storage_path);
$type = explode('/', $media->mimetype)[0];
if ($type === 'image' && !isDisplayableImage($media->mimetype)) {
$type = 'application';
$media->mimetype = 'application/octet-stream';
}
if ($type === 'text') {
if ($size <= (200 * 1024)) { // less than 200 KB
$media->text = $filesystem->read($media->storage_path);
} else {
$type = 'application';
$media->mimetype = 'application/octet-stream';
}
if ($type === 'text') {
if ($size <= (200 * 1024)) { // less than 200 KB
$media->text = $filesystem->read($media->storage_path);
} else {
$type = 'application';
$media->mimetype = 'application/octet-stream';
}
}
$media->size = humanFileSize($size);
} catch (FileNotFoundException $e) {
throw new HttpNotFoundException($request);
}
return view()->render($response, 'upload/public.twig', [
'delete_token' => $token,
'media' => $media,
'type' => $type,
'extension' => pathinfo($media->filename, PATHINFO_EXTENSION),
]);
$media->size = humanFileSize($size);
} catch (FileNotFoundException $e) {
throw new HttpNotFoundException($request);
}
return view()->render($response, 'upload/public.twig', [
'delete_token' => $token,
'media' => $media,
'type' => $type,
'url' => urlFor("/{$userCode}/{$mediaCode}"),
]);
}
/**
* @param Request $request
* @param Response $response
* @param int $id
*
* @throws FileNotFoundException
* @throws HttpNotFoundException
* @param Request $request
* @param Response $response
* @param int $id
*
* @return Response
* @throws HttpNotFoundException
*
* @throws FileNotFoundException
*/
public function getRawById(Request $request, Response $response, int $id): Response
{
@ -96,17 +96,17 @@ class MediaController extends Controller
}
/**
* @param Request $request
* @param Response $response
* @param string $userCode
* @param string $mediaCode
* @param string|null $ext
* @param Request $request
* @param Response $response
* @param string $userCode
* @param string $mediaCode
* @param string|null $ext
*
* @throws FileNotFoundException
* @return Response
* @throws HttpBadRequestException
* @throws HttpNotFoundException
*
* @return Response
* @throws FileNotFoundException
*/
public function getRaw(Request $request, Response $response, string $userCode, string $mediaCode, ?string $ext = null): Response
{
@ -124,15 +124,15 @@ class MediaController extends Controller
}
/**
* @param Request $request
* @param Response $response
* @param string $userCode
* @param string $mediaCode
*
* @throws FileNotFoundException
* @throws HttpNotFoundException
* @param Request $request
* @param Response $response
* @param string $userCode
* @param string $mediaCode
*
* @return Response
* @throws HttpNotFoundException
*
* @throws FileNotFoundException
*/
public function download(Request $request, Response $response, string $userCode, string $mediaCode): Response
{
@ -146,13 +146,13 @@ class MediaController extends Controller
}
/**
* @param Request $request
* @param Response $response
* @param int $id
*
* @throws HttpNotFoundException
* @param Request $request
* @param Response $response
* @param int $id
*
* @return Response
* @throws HttpNotFoundException
*
*/
public function togglePublish(Request $request, Response $response, int $id): Response
{
@ -172,14 +172,14 @@ class MediaController extends Controller
}
/**
* @param Request $request
* @param Response $response
* @param int $id
*
* @throws HttpNotFoundException
* @throws HttpUnauthorizedException
* @param Request $request
* @param Response $response
* @param int $id
*
* @return Response
* @throws HttpUnauthorizedException
*
* @throws HttpNotFoundException
*/
public function delete(Request $request, Response $response, int $id): Response
{
@ -197,20 +197,24 @@ class MediaController extends Controller
throw new HttpUnauthorizedException($request);
}
if ($request->getMethod() === 'GET') {
return redirect($response, route('home'));
}
return $response;
}
/**
* @param Request $request
* @param Response $response
* @param string $userCode
* @param string $mediaCode
* @param string $token
*
* @throws HttpNotFoundException
* @throws HttpUnauthorizedException
* @param Request $request
* @param Response $response
* @param string $userCode
* @param string $mediaCode
* @param string $token
*
* @return Response
* @throws HttpUnauthorizedException
*
* @throws HttpNotFoundException
*/
public function deleteByToken(Request $request, Response $response, string $userCode, string $mediaCode, string $token): Response
{
@ -245,9 +249,9 @@ class MediaController extends Controller
}
/**
* @param Request $request
* @param string $storagePath
* @param int $id
* @param Request $request
* @param string $storagePath
* @param int $id
*
* @throws HttpNotFoundException
*/
@ -281,15 +285,15 @@ class MediaController extends Controller
}
/**
* @param Request $request
* @param Response $response
* @param Filesystem $storage
* @param Request $request
* @param Response $response
* @param Filesystem $storage
* @param $media
* @param string $disposition
*
* @throws FileNotFoundException
* @param string $disposition
*
* @return Response
* @throws FileNotFoundException
*
*/
protected function streamMedia(Request $request, Response $response, Filesystem $storage, $media, string $disposition = 'inline'): Response
{
@ -320,15 +324,15 @@ class MediaController extends Controller
}
/**
* @param Filesystem $storage
* @param Filesystem $storage
* @param $media
* @param null $width
* @param null $height
* @param string $disposition
*
* @throws FileNotFoundException
* @param null $width
* @param null $height
* @param string $disposition
*
* @return Response
* @throws FileNotFoundException
*
*/
protected function makeThumbnail(Filesystem $storage, $media, $width = null, $height = null, string $disposition = 'inline')
{
@ -342,10 +346,10 @@ class MediaController extends Controller
}
/**
* @param Response $response
* @param Stream $stream
* @param string $range
* @param string $disposition
* @param Response $response
* @param Stream $stream
* @param string $range
* @param string $disposition
* @param $media
* @param $mime
*
@ -367,11 +371,11 @@ class MediaController extends Controller
}
if ($range === '-') {
$start = $stream->getSize() - (int) substr($range, 1);
$start = $stream->getSize() - (int)substr($range, 1);
} else {
$range = explode('-', $range);
$start = (int) $range[0];
$end = (isset($range[1]) && is_numeric($range[1])) ? (int) $range[1] : $stream->getSize();
$start = (int)$range[0];
$end = (isset($range[1]) && is_numeric($range[1])) ? (int)$range[1] : $stream->getSize();
}
$end = ($end > $stream->getSize() - 1) ? $stream->getSize() - 1 : $end;

View file

@ -9,14 +9,14 @@ use Psr\Http\Message\ServerRequestInterface as Request;
class UploadController extends Controller
{
/**
* @param Request $request
* @param Response $response
* @param Request $request
* @param Response $response
*
* @throws \Twig\Error\LoaderError
* @return Response
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
*
* @return Response
* @throws \Twig\Error\LoaderError
*/
public function webUpload(Request $request, Response $response): Response
{
@ -34,12 +34,12 @@ class UploadController extends Controller
}
/**
* @param Request $request
* @param Response $response
*
* @throws FileExistsException
* @param Request $request
* @param Response $response
*
* @return Response
* @throws FileExistsException
*
*/
public function upload(Request $request, Response $response): Response
{
@ -113,7 +113,7 @@ class UploadController extends Controller
]);
$json['message'] = 'OK.';
$json['url'] = urlFor("/$user->user_code/$code.$fileInfo[extension]");
$json['url'] = urlFor("/{$user->user_code}/{$code}.{$fileInfo['extension']}");
$this->logger->info("User $user->username uploaded new media.", [$this->database->getPdo()->lastInsertId()]);

View file

@ -57,7 +57,7 @@ $app->group('', function (RouteCollectorProxy $group) {
$group->post('/upload/{id}/publish', [MediaController::class, 'togglePublish'])->setName('upload.publish');
$group->post('/upload/{id}/unpublish', [MediaController::class, 'togglePublish'])->setName('upload.unpublish');
$group->get('/upload/{id}/raw', [MediaController::class, 'getRawById'])->add(AdminMiddleware::class)->setName('upload.raw');
$group->post('/upload/{id}/delete', [MediaController::class, 'delete'])->setName('upload.delete');
$group->map(['GET', 'POST'],'/upload/{id}/delete', [MediaController::class, 'delete'])->setName('upload.delete');
})->add(App\Middleware\CheckForMaintenanceMiddleware::class)->add(AuthMiddleware::class);
$app->get('/', [DashboardController::class, 'redirects'])->setName('root');

View file

@ -0,0 +1,19 @@
<div class="modal fade" id="modalDelete" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{{ lang('confirm') }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>{{ lang('confirm_string') }}</p>
</div>
<div class="modal-footer">
<a href="#" class="btn btn-danger" id="modalDelete-link"><i class="fas fa-trash fa-fw"></i> {{ lang('delete') }}</a>
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ lang('no') }}</button>
</div>
</div>
</div>
</div>

View file

@ -3,8 +3,8 @@
{% block title %}{{ media.filename }}{% endblock %}
{% block head %}
{% if type in ['image', 'text'] %}
<link rel="preload" href="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/raw') }}" as="{{ type }}">
{% if type == 'image' %}
<link rel="preload" href="{{ url }}/raw" as="{{ type }}">
{% endif %}
{% endblock %}
@ -17,10 +17,13 @@
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<div class="ml-auto">
<a href="javascript:void(0)" class="btn btn-success my-2 my-sm-0 btn-clipboard" data-toggle="tooltip" title="{{ lang('copy_link') }}" data-clipboard-text="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension) }}"><i class="fas fa-link fa-lg fa-fw"></i></a>
<a href="javascript:void(0)" class="btn btn-success my-2 my-sm-0 btn-clipboard" data-toggle="tooltip" title="{{ lang('copy_link') }}" data-clipboard-text="{{ url }}"><i class="fas fa-link fa-lg fa-fw"></i></a>
<a href="javascript:void(0)" class="btn btn-info my-2 my-sm-0" data-toggle="tooltip" title="{{ lang('public.telegram') }}" onclick="$('#modalTelegramShare').modal('toggle')"><i class="fab fa-telegram-plane fa-lg fa-fw"></i></a>
<a href="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/raw') }}" class="btn btn-secondary my-2 my-sm-0" data-toggle="tooltip" title="{{ lang('raw') }}"><i class="fas fa-file-alt fa-lg fa-fw"></i></a>
<a href="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/download') }}" class="btn btn-danger my-2 my-sm-0" data-toggle="tooltip" title="{{ lang('download') }}"><i class="fas fa-cloud-download-alt fa-lg fa-fw"></i></a>
<a href="{{ url }}/raw" class="btn btn-secondary my-2 my-sm-0" data-toggle="tooltip" title="{{ lang('raw') }}"><i class="fas fa-file-alt fa-lg fa-fw"></i></a>
<a href="{{ url }}/download" class="btn btn-warning my-2 my-sm-0" data-toggle="tooltip" title="{{ lang('download') }}"><i class="fas fa-cloud-download-alt fa-lg fa-fw"></i></a>
{% if session.get('logged') %}
<a href="javascript:void(0)" class="btn btn-danger my-2 my-sm-0 public-delete" data-link="{{ route('upload.delete', {'id': media.mediaId}) }}" data-toggle="tooltip" title="{{ lang('delete') }}"><i class="fas fa-trash fa-lg fa-fw"></i></a>
{% endif %}
</div>
</div>
</div>
@ -30,12 +33,12 @@
<div class="row ml-auto mr-auto">
<div class="col-md-12 justify-content-center">
{% if delete_token is not null %}
<form method="post" action="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/delete/' ~ delete_token) }}">
<form method="post" action="{{ url }}/delete/{{ delete_token }}">
<div class="text-center mb-4">
<p>{{ lang('public.delete_text') }}</p>
<div class="btn-group">
<button type="submit" class="btn btn-danger"><i class="fas fa-trash"></i> {{ lang('yes') }}</button>
<a href="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension) }}" class="btn btn-secondary">{{ lang('no') }}</a>
<a href="{{ url }}" class="btn btn-secondary">{{ lang('no') }}</a>
</div>
</div>
</form>
@ -43,7 +46,7 @@
{% if type is same as ('image') %}
<div class="row mb-2">
<div class="col-md-12">
<img src="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/raw') }}" class="img-thumbnail rounded mx-auto d-block" alt="{{ media.filename }}">
<img src="{{ url }}/raw" class="img-thumbnail rounded mx-auto d-block" alt="{{ media.filename }}">
</div>
</div>
<div class="row">
@ -65,23 +68,23 @@
{% elseif type is same as ('audio') %}
<div class="media-player media-audio">
<audio id="player" autoplay controls loop preload="auto">
<source src="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/raw') }}" type="{{ media.mimetype }}">
<source src="{{ url }}/raw" type="{{ media.mimetype }}">
Your browser does not support HTML5 audio.
<a href="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/download') }}" class="btn btn-dark btn-lg"><i class="fas fa-cloud-download-alt fa-fw"></i> Download</a>
<a href="{{ url }}/download" class="btn btn-dark btn-lg"><i class="fas fa-cloud-download-alt fa-fw"></i> Download</a>
</audio>
</div>
{% elseif type is same as ('video') %}
<div class="media-player">
<video id="player" autoplay controls loop preload="auto">
<source src="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/raw') }}" type="{{ media.mimetype }}">
<source src="{{ url }}/raw" type="{{ media.mimetype }}">
Your browser does not support HTML5 video.
<a href="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/download') }}" class="btn btn-dark btn-lg"><i class="fas fa-cloud-download-alt fa-fw"></i> Download</a>
<a href="{{ url }}/download" class="btn btn-dark btn-lg"><i class="fas fa-cloud-download-alt fa-fw"></i> Download</a>
</video>
</div>
{% elseif media.mimetype is same as ('application/pdf') %}
<object type="{{ media.mimetype }}" data="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/raw') }}" class="pdf-viewer">
<object type="{{ media.mimetype }}" data="{{ url }}/raw" class="pdf-viewer">
Your browser does not support PDF previews.
<a href="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/download') }}" class="btn btn-dark btn-lg"><i class="fas fa-cloud-download-alt fa-fw"></i> Download</a>
<a href="{{ url }}/download" class="btn btn-dark btn-lg"><i class="fas fa-cloud-download-alt fa-fw"></i> Download</a>
</object>
{% else %}
<div class="text-center">
@ -102,7 +105,7 @@
</div>
<div class="row">
<div class="col-md-12">
<a href="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/download') }}" class="btn btn-dark btn-lg"><i class="fas fa-cloud-download-alt fa-fw"></i> Download</a>
<a href="{{ url }}/download" class="btn btn-dark btn-lg"><i class="fas fa-cloud-download-alt fa-fw"></i> Download</a>
</div>
</div>
</div>
@ -123,11 +126,12 @@
<textarea type="text" class="form-control mb-2" id="telegram-share-text" onclick="this.select()">{{ media.filename }}</textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-info btn-block" id="telegram-share-button" onclick="app.telegramShare()" data-url="https://telegram.me/share/url?url={{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension) }}&text=">
<button type="button" class="btn btn-info btn-block" id="telegram-share-button" onclick="app.telegramShare()" data-url="https://telegram.me/share/url?url={{ url }}&text=">
<i class="fab fa-telegram-plane fa-lg fa-fw"></i> {{ lang("send") }}</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ lang('cancel') }}</button>
</div>
</div>
</div>
</div>
{% include 'comp/modal_delete.twig' %}
{% endblock %}

View file

@ -8,15 +8,26 @@
{% include 'comp/alert.twig' %}
<div class="card shadow-sm">
<div class="card-body">
<div class="progress mb-3">
<div class="progress-bar progress-bar-animated progress-bar-striped" style="width: 0;" id="uploadProgess"></div>
</div>
<form action="{{ route('upload') }}" method="post" id="upload-dropzone" class="dropzone">
<div class="fallback">
<input name="file" type="file" multiple>
<div class="row mb-3">
<div class="col-10">
<div class="progress h-100">
<div class="progress-bar progress-bar-animated progress-bar-striped" style="width: 0;" id="uploadProgess"></div>
</div>
</div>
<input type="hidden" name="token" value="{{ user.token }}">
</form>
<div class="col-2 text-center">
<button type="button" class="btn btn-sm btn-outline-danger btn-block" onclick="Dropzone.instances[0].removeAllFiles(true)" data-toggle="tooltip" title="{{ lang('cancel') }}"><i class="fas fa-times"></i></button>
</div>
</div>
<div class="row">
<div class="col">
<form action="{{ route('upload') }}" method="post" id="upload-dropzone" class="dropzone">
<div class="fallback">
<input name="file" type="file" multiple>
</div>
<input type="hidden" name="token" value="{{ user.token }}">
</form>
</div>
</div>
</div>
</div>
</div>

View file

@ -54,7 +54,7 @@
<td class="text-right">
<div class="btn-group">
<a href="{{ route('user.edit', {'id': user.id}) }}" class="btn btn-outline-warning" data-toggle="tooltip" title="{{ lang('edit') }}"><i class="fas fa-pencil-alt"></i></a>
<a href="#" class="btn btn-outline-danger user-delete" data-link="{{ route('user.delete', {'id': user.id}) }}" data-toggle="tooltip" title="{{ lang('delete') }}"><i class="fas fa-trash"></i></a>
<a href="javascript:void(0)" class="btn btn-outline-danger user-delete" data-link="{{ route('user.delete', {'id': user.id}) }}" data-toggle="tooltip" title="{{ lang('delete') }}"><i class="fas fa-trash"></i></a>
</div>
</td>
</tr>
@ -68,23 +68,5 @@
</div>
</div>
</div>
<div class="modal fade" id="modalDelete" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{{ lang('confirm') }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>{{ lang('confirm_string') }}</p>
</div>
<div class="modal-footer">
<a href="#" class="btn btn-danger" id="modalDelete-link"><i class="fas fa-trash fa-fw"></i> {{ lang('delete') }}</a>
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ lang('no') }}</button>
</div>
</div>
</div>
</div>
{% include 'comp/modal_delete.twig' %}
{% endblock %}

View file

@ -18,6 +18,7 @@ var app = {
$('[data-toggle="popover"]').popover();
$('.user-delete').click(app.modalDelete);
$('.public-delete').click(app.modalDelete);
$('.media-delete').click(app.mediaDelete);
$('.publish-toggle').click(app.publishToggle);
$('.refresh-token').click(app.refreshToken);