commit
7f07ecdfad
8 changed files with 91 additions and 1 deletions
|
@ -188,6 +188,43 @@ class MediaController extends Controller
|
||||||
return $this->streamMedia($request, $response, $this->storage, $media, 'attachment');
|
return $this->streamMedia($request, $response, $this->storage, $media, 'attachment');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param Response $response
|
||||||
|
* @param string $vanity
|
||||||
|
* @param string $id
|
||||||
|
*
|
||||||
|
* @return Response
|
||||||
|
* @throws HttpNotFoundException
|
||||||
|
* @throws HttpBadRequestException
|
||||||
|
*/
|
||||||
|
public function createVanity(Request $request, Response $response, int $id): Response
|
||||||
|
{
|
||||||
|
$media = $this->database->query('SELECT * FROM `uploads` WHERE `id` = ? LIMIT 1', $id)->fetch();
|
||||||
|
|
||||||
|
$vanity = param($request, 'vanity');
|
||||||
|
$vanity = preg_replace('/[^a-z0-9]+/', '-', strtolower($vanity));
|
||||||
|
|
||||||
|
//handle collisions
|
||||||
|
$collision = $this->database->query('SELECT * FROM `uploads` WHERE `code` = ? AND `id` != ? LIMIT 1', [$vanity, $id])->fetch();
|
||||||
|
|
||||||
|
if (!$media) {
|
||||||
|
throw new HttpNotFoundException($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($vanity === '' || $collision) {
|
||||||
|
throw new HttpBadRequestException($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->database->query('UPDATE `uploads` SET `code` = ? WHERE `id` = ?', [$vanity, $media->id]);
|
||||||
|
$media->code = $vanity;
|
||||||
|
$response->getBody()->write(json_encode($media));
|
||||||
|
|
||||||
|
$this->logger->info('User '.$this->session->get('username').' created a vanity link for media '.$media->id);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @param Response $response
|
* @param Response $response
|
||||||
|
|
1
app/routes.php
Normal file → Executable file
1
app/routes.php
Normal file → Executable file
|
@ -62,6 +62,7 @@ $app->group('', function (RouteCollectorProxy $group) {
|
||||||
|
|
||||||
$group->post('/upload/{id}/publish', [MediaController::class, 'togglePublish'])->setName('upload.publish');
|
$group->post('/upload/{id}/publish', [MediaController::class, 'togglePublish'])->setName('upload.publish');
|
||||||
$group->post('/upload/{id}/unpublish', [MediaController::class, 'togglePublish'])->setName('upload.unpublish');
|
$group->post('/upload/{id}/unpublish', [MediaController::class, 'togglePublish'])->setName('upload.unpublish');
|
||||||
|
$group->post('/upload/{id}/vanity', [MediaController::class, 'createVanity'])->setName('upload.vanity');
|
||||||
$group->get('/upload/{id}/raw', [MediaController::class, 'getRawById'])->add(AdminMiddleware::class)->setName('upload.raw');
|
$group->get('/upload/{id}/raw', [MediaController::class, 'getRawById'])->add(AdminMiddleware::class)->setName('upload.raw');
|
||||||
$group->map(['GET', 'POST'], '/upload/{id}/delete', [MediaController::class, 'delete'])->setName('upload.delete');
|
$group->map(['GET', 'POST'], '/upload/{id}/delete', [MediaController::class, 'delete'])->setName('upload.delete');
|
||||||
|
|
||||||
|
|
3
resources/lang/en.lang.php
Normal file → Executable file
3
resources/lang/en.lang.php
Normal file → Executable file
|
@ -30,6 +30,8 @@ return [
|
||||||
'download' => 'Download',
|
'download' => 'Download',
|
||||||
'upload' => 'Upload',
|
'upload' => 'Upload',
|
||||||
'delete' => 'Delete',
|
'delete' => 'Delete',
|
||||||
|
'confirm' => 'Confirm',
|
||||||
|
'vanity_url' => 'Custom URL',
|
||||||
'publish' => 'Publish',
|
'publish' => 'Publish',
|
||||||
'hide' => 'Hide',
|
'hide' => 'Hide',
|
||||||
'files' => 'Files',
|
'files' => 'Files',
|
||||||
|
@ -58,7 +60,6 @@ return [
|
||||||
'reg_date' => 'Registration Date',
|
'reg_date' => 'Registration Date',
|
||||||
'none' => 'None',
|
'none' => 'None',
|
||||||
'open' => 'Open',
|
'open' => 'Open',
|
||||||
'confirm' => 'Confirmation',
|
|
||||||
'confirm_string' => 'Are you sure?',
|
'confirm_string' => 'Are you sure?',
|
||||||
'installed' => 'Installation completed successfully!',
|
'installed' => 'Installation completed successfully!',
|
||||||
'bad_login' => 'Wrong credentials.',
|
'bad_login' => 'Wrong credentials.',
|
||||||
|
|
19
resources/templates/comp/modal_vanity.twig
Executable file
19
resources/templates/comp/modal_vanity.twig
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
<div class="modal fade" id="modalVanity" 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('vanity_url') }}</h5>
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<input type="text" class="form-control" id="modalVanity-input" maxlength="64">
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-primary media-vanity" id="modalVanity-link"><i class="fas fa-check fa-fw"></i> {{ lang('confirm') }}</button>
|
||||||
|
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ lang('no') }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
2
resources/templates/dashboard/grid.twig
Normal file → Executable file
2
resources/templates/dashboard/grid.twig
Normal file → Executable file
|
@ -28,6 +28,7 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<a class="btn btn-sm btn-info publish-toggle" data-toggle="tooltip" title="{{ lang('publish') }}" data-id="{{ media.id }}" data-published="{{ media.published }}"><i class="fas fa-check-circle"></i></a>
|
<a class="btn btn-sm btn-info publish-toggle" data-toggle="tooltip" title="{{ lang('publish') }}" data-id="{{ media.id }}" data-published="{{ media.published }}"><i class="fas fa-check-circle"></i></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<button class="btn btn-info btn-sm public-vanity" data-id="{{ media.id }}" data-toggle="tooltip" title="{{ lang('vanity_url') }}"><i class="fas fa-star"></i></button>
|
||||||
<button type="button" class="btn btn-sm btn-danger media-delete" data-link="{{ route('upload.delete', {'id': media.id}) }}" data-id="{{ media.id }}" data-toggle="tooltip" title="{{ lang('delete') }}">
|
<button type="button" class="btn btn-sm btn-danger media-delete" data-link="{{ route('upload.delete', {'id': media.id}) }}" data-id="{{ media.id }}" data-toggle="tooltip" title="{{ lang('delete') }}">
|
||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
|
@ -68,4 +69,5 @@
|
||||||
<div class="text-center text-muted"><i>{{ lang('no_media') }}</i></div>
|
<div class="text-center text-muted"><i>{{ lang('no_media') }}</i></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
{% include 'comp/modal_vanity.twig' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
2
resources/templates/dashboard/list.twig
Normal file → Executable file
2
resources/templates/dashboard/list.twig
Normal file → Executable file
|
@ -6,6 +6,7 @@
|
||||||
{% include 'comp/navbar.twig' %}
|
{% include 'comp/navbar.twig' %}
|
||||||
<div class="container">
|
<div class="container">
|
||||||
{% include 'comp/alert.twig' %}
|
{% include 'comp/alert.twig' %}
|
||||||
|
{% include 'comp/modal_vanity.twig' %}
|
||||||
|
|
||||||
<div class="card shadow-sm">
|
<div class="card shadow-sm">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
@ -77,6 +78,7 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="javascript:void(0)" class="btn btn-sm btn-outline-info publish-toggle" data-toggle="tooltip" title="{{ lang('publish') }}" data-id="{{ media.id }}" data-published="{{ media.published }}"><i class="fas fa-check-circle"></i></a>
|
<a href="javascript:void(0)" class="btn btn-sm btn-outline-info publish-toggle" data-toggle="tooltip" title="{{ lang('publish') }}" data-id="{{ media.id }}" data-published="{{ media.published }}"><i class="fas fa-check-circle"></i></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<a href="javascript:void(0)" class="btn btn-sm btn-outline-info public-vanity" data-id="{{ media.id }}" data-toggle="tooltip" title="{{ lang('vanity_url') }}"><i class="fas fa-star"></i></a>
|
||||||
<a href="javascript:void(0)" class="btn btn-sm btn-outline-danger media-delete" data-link="{{ route('upload.delete', {'id': media.id}) }}" data-id="{{ media.id }}" data-toggle="tooltip" title="{{ lang('delete') }}"><i class="fas fa-trash"></i></a>
|
<a href="javascript:void(0)" class="btn btn-sm btn-outline-danger media-delete" data-link="{{ route('upload.delete', {'id': media.id}) }}" data-id="{{ media.id }}" data-toggle="tooltip" title="{{ lang('delete') }}"><i class="fas fa-trash"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
2
resources/templates/upload/public.twig
Normal file → Executable file
2
resources/templates/upload/public.twig
Normal file → Executable file
|
@ -49,6 +49,7 @@
|
||||||
<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 }}/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>
|
<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') %}
|
{% if session.get('logged') %}
|
||||||
|
<a href="javascript:void(0)" class="btn btn-info my-2 my-sm-0 public-vanity" data-link="{{ route('upload.vanity', {'id': media.mediaId}) }}" data-id="{{ media.mediaId }}" data-toggle="tooltip" title="{{ lang('vanity') }}"><i class="fas fa-star fa-lg fa-fw"></i></a>
|
||||||
<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>
|
<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 %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -162,4 +163,5 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% include 'comp/modal_delete.twig' %}
|
{% include 'comp/modal_delete.twig' %}
|
||||||
|
{% include 'comp/modal_vanity.twig' %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
26
src/js/app.js
Normal file → Executable file
26
src/js/app.js
Normal file → Executable file
|
@ -29,8 +29,10 @@ var app = {
|
||||||
|
|
||||||
$('.user-delete').click(app.modalDelete);
|
$('.user-delete').click(app.modalDelete);
|
||||||
$('.public-delete').click(app.modalDelete);
|
$('.public-delete').click(app.modalDelete);
|
||||||
|
$('.public-vanity').click(app.modalVanity);
|
||||||
$('.media-delete').click(app.mediaDelete);
|
$('.media-delete').click(app.mediaDelete);
|
||||||
$('.publish-toggle').click(app.publishToggle);
|
$('.publish-toggle').click(app.publishToggle);
|
||||||
|
|
||||||
$('.refresh-token').click(app.refreshToken);
|
$('.refresh-token').click(app.refreshToken);
|
||||||
$('#themes').mousedown(app.loadThemes);
|
$('#themes').mousedown(app.loadThemes);
|
||||||
$('.checkForUpdatesButton').click(app.checkForUpdates);
|
$('.checkForUpdatesButton').click(app.checkForUpdates);
|
||||||
|
@ -57,6 +59,30 @@ var app = {
|
||||||
$('#modalDelete-link').attr('href', $(this).data('link'));
|
$('#modalDelete-link').attr('href', $(this).data('link'));
|
||||||
$('#modalDelete').modal('show');
|
$('#modalDelete').modal('show');
|
||||||
},
|
},
|
||||||
|
modalVanity: function () {
|
||||||
|
var id = $(this).data('id');
|
||||||
|
$('#modalVanity').modal('show');
|
||||||
|
$('#modalVanity-link').click(function () {
|
||||||
|
var $callerButton = $(this);
|
||||||
|
$.post(window.AppConfig.base_url + '/upload/' + id + '/vanity', {vanity: $('#modalVanity-input').val()}, function (responseData, status) {
|
||||||
|
$callerButton.tooltip('dispose');
|
||||||
|
$('#modalVanity').modal('hide');
|
||||||
|
$('#modalVanity-input').val('');
|
||||||
|
var parsedData = JSON.parse(responseData);
|
||||||
|
if ($('#media_' + id).find('.btn-group').length > 0) {
|
||||||
|
$('#media_' + id).find('.btn-group').find('a').each(function (item) {
|
||||||
|
var oldUrl = $(this).attr('href');
|
||||||
|
var newUrl = oldUrl.replace(oldUrl.substr(oldUrl.lastIndexOf('/') + 1), parsedData.code.code);
|
||||||
|
$(this).attr('href', newUrl);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var oldUrl = window.location.href;
|
||||||
|
var newUrl = oldUrl.replace(oldUrl.substr(oldUrl.lastIndexOf('/') + 1), parsedData.code.code);
|
||||||
|
window.location.href = newUrl;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
publishToggle: function () {
|
publishToggle: function () {
|
||||||
var id = $(this).data('id');
|
var id = $(this).data('id');
|
||||||
var $callerButton = $(this);
|
var $callerButton = $(this);
|
||||||
|
|
Loading…
Reference in a new issue