Implemented a better multi-file upload for browsers that support it. Started adding support for bulk modifying photos (e.g. rotating)
This commit is contained in:
parent
08f13b28cb
commit
63e341199b
@ -127,6 +127,13 @@ class AlbumController extends Controller
|
|||||||
|
|
||||||
return Theme::render('admin.show_album', [
|
return Theme::render('admin.show_album', [
|
||||||
'album' => $album,
|
'album' => $album,
|
||||||
|
'bulk_actions' => [
|
||||||
|
'rotate_left' => trans('admin.photo_actions.rotate_left'),
|
||||||
|
'rotate_right' => trans('admin.photo_actions.rotate_right'),
|
||||||
|
'-' => '-----',
|
||||||
|
'refresh_thumbnails' => trans('admin.photo_actions.refresh_thumbnails'),
|
||||||
|
'delete' => trans('admin.photo_actions.delete')
|
||||||
|
],
|
||||||
'error' => $request->session()->get('error'),
|
'error' => $request->session()->get('error'),
|
||||||
'photos' => $photos
|
'photos' => $photos
|
||||||
]);
|
]);
|
||||||
|
@ -184,9 +184,16 @@ class PhotoController extends Controller
|
|||||||
$photo->save();
|
$photo->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect(route('albums.analyse', [
|
if ($request->isXmlHttpRequest())
|
||||||
'id' => $album->id
|
{
|
||||||
]));
|
return response()->json(['is_successful' => true]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return redirect(route('albums.analyse', [
|
||||||
|
'id' => $album->id
|
||||||
|
]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function storeBulk(Request $request)
|
public function storeBulk(Request $request)
|
||||||
@ -303,6 +310,9 @@ class PhotoController extends Controller
|
|||||||
{
|
{
|
||||||
$photos = $request->get('photo');
|
$photos = $request->get('photo');
|
||||||
|
|
||||||
|
dump($request->all());
|
||||||
|
exit();
|
||||||
|
|
||||||
/** @var Album $album */
|
/** @var Album $album */
|
||||||
$album = Album::where('id', intval($albumId))->first();
|
$album = Album::where('id', intval($albumId))->first();
|
||||||
|
|
||||||
|
@ -19,12 +19,21 @@ return [
|
|||||||
'edit_album' => 'Edit photo album: :album_name',
|
'edit_album' => 'Edit photo album: :album_name',
|
||||||
'edit_album_intro' => 'Photo albums contain individual photographs together in the same way as a physical photo album or memory book.',
|
'edit_album_intro' => 'Photo albums contain individual photographs together in the same way as a physical photo album or memory book.',
|
||||||
'edit_album_intro2' => 'Complete the form below to edit the properties of the album: :album_name.',
|
'edit_album_intro2' => 'Complete the form below to edit the properties of the album: :album_name.',
|
||||||
|
'upload_file_not_image_messages' => 'The file ":file_name" is not recognised as an image and won\'t be uploaded.',
|
||||||
|
'upload_file_status_failed' => ':file_name failed to upload',
|
||||||
|
'upload_file_status_success' => ':file_name uploaded successfully',
|
||||||
'manage_widget' => [
|
'manage_widget' => [
|
||||||
'panel_header' => 'Manage'
|
'panel_header' => 'Manage'
|
||||||
],
|
],
|
||||||
'no_albums_text' => 'You have no photo albums yet. Click the button below to create one.',
|
'no_albums_text' => 'You have no photo albums yet. Click the button below to create one.',
|
||||||
'no_albums_title' => 'No Photo Albums',
|
'no_albums_title' => 'No Photo Albums',
|
||||||
'open_album' => 'Open album',
|
'open_album' => 'Open album',
|
||||||
|
'photo_actions' => [
|
||||||
|
'delete' => 'Delete',
|
||||||
|
'refresh_thumbnails' => 'Refresh thumbnails',
|
||||||
|
'rotate_left' => 'Rotate left',
|
||||||
|
'rotate_right' => 'Rotate right'
|
||||||
|
],
|
||||||
'settings_image_protection' => 'Image Protection',
|
'settings_image_protection' => 'Image Protection',
|
||||||
'settings_link' => 'Settings',
|
'settings_link' => 'Settings',
|
||||||
'settings_recaptcha' => 'reCAPTCHA settings',
|
'settings_recaptcha' => 'reCAPTCHA settings',
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
return [
|
return [
|
||||||
|
'apply_action' => 'Apply',
|
||||||
|
'bulk_edit_photos_label' => 'Bulk edit selected photos:',
|
||||||
|
'bulk_edit_photos_placeholder' => 'Select an action',
|
||||||
'cancel_action' => 'Cancel',
|
'cancel_action' => 'Cancel',
|
||||||
'create_action' => 'Create',
|
'create_action' => 'Create',
|
||||||
'delete_action' => 'Delete',
|
'delete_action' => 'Delete',
|
||||||
@ -14,6 +17,7 @@ return [
|
|||||||
'realname_label' => 'Your name:',
|
'realname_label' => 'Your name:',
|
||||||
'register_action' => 'Create account',
|
'register_action' => 'Create account',
|
||||||
'remember_me_label' => 'Remember me',
|
'remember_me_label' => 'Remember me',
|
||||||
|
'select' => 'Select',
|
||||||
'settings_hotlink_protection' => 'Prevent hot-linking to images',
|
'settings_hotlink_protection' => 'Prevent hot-linking to images',
|
||||||
'settings_hotlink_protection_help' => 'With this option enabled, direct linking to images is not allowed. Photos can only be viewed through Blue Twilight.',
|
'settings_hotlink_protection_help' => 'With this option enabled, direct linking to images is not allowed. Photos can only be viewed through Blue Twilight.',
|
||||||
'settings_restrict_originals_download' => 'Restrict access to original images',
|
'settings_restrict_originals_download' => 'Restrict access to original images',
|
||||||
|
@ -47,6 +47,11 @@
|
|||||||
@include (Theme::viewName('partials.single_photo_admin'))
|
@include (Theme::viewName('partials.single_photo_admin'))
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
||||||
|
<div class="pull-left">
|
||||||
|
<p>{!! Form::label('bulk-action', trans('forms.bulk_edit_photos_label'), ['class' => 'control-label']) !!}</p>
|
||||||
|
{!! Form::select('bulk-action', $bulk_actions, null, ['placeholder' => trans('forms.bulk_edit_photos_placeholder'), 'id' => 'bulk-action-apply']) !!}
|
||||||
|
<button type="submit" class="btn btn-sm btn-success" name="bulk-apply" value="clicked">@lang('forms.apply_action')</button>
|
||||||
|
</div>
|
||||||
<div class="pull-right">
|
<div class="pull-right">
|
||||||
<button type="submit" class="btn btn-success">@lang('forms.save_action')</button>
|
<button type="submit" class="btn btn-success">@lang('forms.save_action')</button>
|
||||||
</div>
|
</div>
|
||||||
@ -62,20 +67,37 @@
|
|||||||
|
|
||||||
{{-- Upload --}}
|
{{-- Upload --}}
|
||||||
<div role="tabpanel" class="tab-pane" id="upload-tab">
|
<div role="tabpanel" class="tab-pane" id="upload-tab">
|
||||||
<h4>Upload single images</h4>
|
<h4>Upload images</h4>
|
||||||
|
|
||||||
{!! Form::open(['route' => 'photos.store', 'method' => 'POST', 'files' => true]) !!}
|
<div class="row">
|
||||||
{!! Form::hidden('album_id', $album->id) !!}
|
<div class="col-sm-5">
|
||||||
|
{!! Form::open(['route' => 'photos.store', 'method' => 'POST', 'files' => true, 'id' => 'single-upload-form']) !!}
|
||||||
|
{!! Form::hidden('album_id', $album->id) !!}
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
{!! Form::file('photo[]', ['class' => 'control-label', 'multiple' => 'multiple']) !!}
|
{!! Form::file('photo[]', ['class' => 'control-label', 'multiple' => 'multiple', 'id' => 'single-upload-files']) !!}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button type="submit" class="btn btn-success">@lang('forms.upload_action')</button>
|
||||||
|
</div>
|
||||||
|
{!! Form::close() !!}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-5 text-center" id="upload-progress-bar" style="display: none;">
|
||||||
|
<p><b>Uploading...</b></p>
|
||||||
|
<div class="progress">
|
||||||
|
<div class="progress-bar progress-bar-success" style="width: 0%">
|
||||||
|
<span class="sr-only"><span class="percentage-success">0%</span> Complete (success)</span>
|
||||||
|
</div>
|
||||||
|
<div class="progress-bar progress-bar-danger" style="width: 0%">
|
||||||
|
<span class="sr-only"><span class="percentage-danger">0%</span> Complete (warning)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p id="upload-status-text"></p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
|
||||||
{!! Form::submit(trans('forms.upload_action'), ['class' => 'btn btn-success']) !!}
|
|
||||||
</div>
|
|
||||||
{!! Form::close() !!}
|
|
||||||
|
|
||||||
<hr/>
|
<hr/>
|
||||||
<h4>Bulk upload</h4>
|
<h4>Bulk upload</h4>
|
||||||
|
|
||||||
@ -108,6 +130,10 @@
|
|||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
var images_failed = 0;
|
||||||
|
var images_uploaded = 0;
|
||||||
|
var images_total = 0;
|
||||||
|
|
||||||
function deletePhoto(photo_id, parent)
|
function deletePhoto(photo_id, parent)
|
||||||
{
|
{
|
||||||
var url = '{{ route('photos.destroy', ['id' => 0]) }}';
|
var url = '{{ route('photos.destroy', ['id' => 0]) }}';
|
||||||
@ -154,6 +180,51 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateProgressBar()
|
||||||
|
{
|
||||||
|
if ((images_uploaded > 0 && images_uploaded + images_failed) == images_total)
|
||||||
|
{
|
||||||
|
window.location = '{{ route('albums.analyse', ['id' => $album->id]) }}';
|
||||||
|
}
|
||||||
|
|
||||||
|
var failed_percentage = ((images_failed / images_total) * 100).toFixed(2);
|
||||||
|
var success_percentage = ((images_uploaded / images_total) * 100).toFixed(2);
|
||||||
|
|
||||||
|
$('#upload-progress-bar').show();
|
||||||
|
$('.progress-bar-success', '#upload-progress-bar').css('width', success_percentage + '%');
|
||||||
|
$('.progress-bar-danger', '#upload-progress-bar').css('width', failed_percentage + '%');
|
||||||
|
$('.percentage-success', '#upload-progress-bar').html(success_percentage);
|
||||||
|
$('.percentage-danger', '#upload-progress-bar').html(failed_percentage);
|
||||||
|
}
|
||||||
|
|
||||||
|
function uploadImageFile(formObject, imageFile)
|
||||||
|
{
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append('album_id', '{{ $album->id }}');
|
||||||
|
formData.append('photo[]', imageFile, imageFile.name);
|
||||||
|
|
||||||
|
$.ajax(
|
||||||
|
{
|
||||||
|
complete: function() {
|
||||||
|
updateProgressBar();
|
||||||
|
},
|
||||||
|
contentType: false,
|
||||||
|
data: formData,
|
||||||
|
error: function() {
|
||||||
|
images_failed++;
|
||||||
|
$('#upload-status-text').html('@lang('admin.upload_file_status_failed')'.replace(':file_name', imageFile.name));
|
||||||
|
},
|
||||||
|
method: $(formObject).attr('method'),
|
||||||
|
processData: false,
|
||||||
|
success: function() {
|
||||||
|
images_uploaded++;
|
||||||
|
$('#upload-status-text').html('@lang('admin.upload_file_status_success')'.replace(':file_name', imageFile.name));
|
||||||
|
},
|
||||||
|
url: $(formObject).attr('action')
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('#upload-button').click(function() {
|
$('#upload-button').click(function() {
|
||||||
$('.nav-tabs a[href="#upload-tab"]').tab('show');
|
$('.nav-tabs a[href="#upload-tab"]').tab('show');
|
||||||
@ -210,6 +281,51 @@
|
|||||||
$(this).dropdown('toggle');
|
$(this).dropdown('toggle');
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
{{-- Photo uploads using AJAX --}}
|
||||||
|
if (window.FormData)
|
||||||
|
{
|
||||||
|
$('#single-upload-form').submit(function(event) {
|
||||||
|
var fileSelect = $('#single-upload-files', this);
|
||||||
|
var uploadButton = $('button[type=submit]', this);
|
||||||
|
|
||||||
|
var currentText = uploadButton.html();
|
||||||
|
|
||||||
|
// Update button text
|
||||||
|
uploadButton.attr('disabled', 'disabled');
|
||||||
|
uploadButton.html('Uploading...');
|
||||||
|
|
||||||
|
// Get the selected files
|
||||||
|
var notImageString = '{!! addslashes(trans('admin.upload_file_not_image_messages')) !!}';
|
||||||
|
var files = fileSelect[0].files;
|
||||||
|
|
||||||
|
// Reset statistics
|
||||||
|
images_total = files.length;
|
||||||
|
images_failed = 0;
|
||||||
|
images_uploaded = 0;
|
||||||
|
updateProgressBar();
|
||||||
|
|
||||||
|
// Loop through each of the selected files and upload them individually
|
||||||
|
for (var i = 0; i < files.length; i++)
|
||||||
|
{
|
||||||
|
var file = files[i];
|
||||||
|
|
||||||
|
// We're only interested in image files
|
||||||
|
if (!file.type.match('image.*'))
|
||||||
|
{
|
||||||
|
alert(notImageString.replace(':file_name', file.name));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upload the file
|
||||||
|
uploadImageFile($(this), file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent standard form upload
|
||||||
|
event.preventDefault();
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
@endpush
|
@ -30,6 +30,10 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<p style="margin-top: 10px;">
|
||||||
|
<input type="checkbox" id="select-photo-{{ $photo->id }}" name="select-photo[]" value="{{ $photo->id }}" /> <label for="select-photo-{{ $photo->id }}">@lang('forms.select')</label>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xs-12 col-sm-10">
|
<div class="col-xs-12 col-sm-10">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
Loading…
Reference in New Issue
Block a user