From e5a372ffbd8c4a3a801406fb83038f81433c2e62 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 16 Aug 2015 00:18:22 +0100 Subject: [PATCH] Added image name editing & deleting --- app/Http/Controllers/ImageController.php | 44 +++++++++- app/Http/routes.php | 2 + app/Image.php | 3 + resources/assets/js/image-manager.js | 63 +++++++++++++- resources/assets/sass/_animations.scss | 17 ++++ resources/assets/sass/_forms.scss | 6 ++ resources/assets/sass/_text.scss | 9 +- resources/assets/sass/image-manager.scss | 85 +++++++------------ resources/assets/sass/styles.scss | 1 + resources/views/pages/image-manager.blade.php | 35 ++++++-- 10 files changed, 201 insertions(+), 64 deletions(-) create mode 100644 resources/assets/sass/_animations.scss diff --git a/app/Http/Controllers/ImageController.php b/app/Http/Controllers/ImageController.php index 2ef5b1228..9fcd5c304 100644 --- a/app/Http/Controllers/ImageController.php +++ b/app/Http/Controllers/ImageController.php @@ -10,6 +10,9 @@ use Intervention\Image\Facades\Image as ImageTool; use Illuminate\Support\Facades\DB; use Oxbow\Http\Requests; use Oxbow\Image; +use RecursiveDirectoryIterator; +use RecursiveIteratorIterator; +use RegexIterator; class ImageController extends Controller { @@ -71,7 +74,7 @@ class ImageController extends Controller */ public function getAll($page = 0) { - $pageSize = 25; + $pageSize = 30; $images = DB::table('images')->orderBy('created_at', 'desc') ->skip($page*$pageSize)->take($pageSize)->get(); foreach($images as $image) { @@ -146,5 +149,44 @@ class ImageController extends Controller return response()->json($this->image); } + /** + * Update image details + * @param $imageId + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function update($imageId, Request $request) + { + $this->validate($request, [ + 'name' => 'required|min:2|string' + ]); + $image = $this->image->findOrFail($imageId); + $image->fill($request->all()); + $image->save(); + return response()->json($this->image); + } + + /** + * Deletes an image and all thumbnail/image files + * @param $id + * @return \Illuminate\Http\JsonResponse + */ + public function destroy($id) + { + $image = $this->image->findOrFail($id); + + // Delete files + $folder = public_path() . dirname($image->url); + $pattern = '/' . preg_quote(basename($image->url)). '/'; + $dir = new RecursiveDirectoryIterator($folder); + $ite = new RecursiveIteratorIterator($dir); + $files = new RegexIterator($ite, $pattern, RegexIterator::ALL_MATCHES); + foreach($files as $path => $file) { + unlink($path); + } + $image->delete(); + return response()->json('Image Deleted'); + } + } diff --git a/app/Http/routes.php b/app/Http/routes.php index 0b723b98a..ecda75793 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -68,6 +68,8 @@ Route::group(['middleware' => 'auth'], function() { // Image routes Route::get('/images/all', 'ImageController@getAll'); + Route::put('/images/update/{imageId}', 'ImageController@update'); + Route::delete('/images/{imageId}', 'ImageController@destroy'); Route::get('/images/all/{page}', 'ImageController@getAll'); Route::get('/images/{any}', 'ImageController@getImage')->where('any', '.*'); diff --git a/app/Image.php b/app/Image.php index 9d2835dc3..07db68785 100644 --- a/app/Image.php +++ b/app/Image.php @@ -6,6 +6,9 @@ use Illuminate\Database\Eloquent\Model; class Image extends Model { + + protected $fillable = ['name']; + public function getFilePath() { return storage_path() . $this->url; diff --git a/resources/assets/js/image-manager.js b/resources/assets/js/image-manager.js index 27deed51e..4f8695ff8 100644 --- a/resources/assets/js/image-manager.js +++ b/resources/assets/js/image-manager.js @@ -1,4 +1,30 @@ +jQuery.fn.showSuccess = function(message) { + var elem = $(this); + var success = $(''); + elem.after(success); + success.slideDown(400, function() { + setTimeout(function() {success.slideUp(400, function() { + success.remove(); + })}, 2000); + }); +}; + +jQuery.fn.showFailure = function(messageMap) { + var elem = $(this); + $.each(messageMap, function(key, messages) { + var input = elem.find('[name="'+key+'"]').last(); + var fail = $(''); + input.after(fail); + fail.slideDown(400, function() { + setTimeout(function() {fail.slideUp(400, function() { + fail.remove(); + })}, 2000); + }); + }); + +}; + (function() { var ImageManager = new Vue({ @@ -56,7 +82,7 @@ var dblClickTime = 380; var cTime = (new Date()).getTime(); var timeDiff = cTime - this.cClickTime; - if(this.cClickTime !== 0 && timeDiff < dblClickTime) { + if(this.cClickTime !== 0 && timeDiff < dblClickTime && this.selectedImage === image) { // DoubleClick if(this.callback) { this.callback(image); @@ -68,6 +94,13 @@ this.cClickTime = cTime; }, + selectButtonClick: function() { + if(this.callback) { + this.callback(this.selectedImage); + } + this.hide(); + }, + show: function(callback) { this.callback = callback; this.$$.overlay.style.display = 'block'; @@ -81,6 +114,34 @@ hide: function() { this.$$.overlay.style.display = 'none'; + }, + + saveImageDetails: function(e) { + e.preventDefault(); + var _this = this; + var form = $(_this.$$.imageForm); + $.ajax('/images/update/' + _this.selectedImage.id, { + method: 'PUT', + data: form.serialize() + }).done(function() { + form.showSuccess('Image name updated'); + }).fail(function(jqXHR) { + form.showFailure(jqXHR.responseJSON); + }) + }, + + deleteImage: function(e) { + e.preventDefault(); + var _this = this; + var form = $(_this.$$.imageDeleteForm); + $.ajax('/images/' + _this.selectedImage.id, { + method: 'DELETE', + data: form.serialize() + }).done(function() { + _this.images.splice(_this.images.indexOf(_this.selectedImage), 1); + _this.selectedImage = false; + $(_this.$$.imageTitle).showSuccess('Image Deleted'); + }) } } diff --git a/resources/assets/sass/_animations.scss b/resources/assets/sass/_animations.scss new file mode 100644 index 000000000..147197e1d --- /dev/null +++ b/resources/assets/sass/_animations.scss @@ -0,0 +1,17 @@ + +.anim.fadeIn { + opacity: 0; + animation-name: fadeIn; + animation-duration: 160ms; + animation-timing-function: ease-in-out; + animation-fill-mode: forwards; +} + +@keyframes fadeIn { + 0% { + opacity: 0; + } + 100% { + opacity: 1; + } +} \ No newline at end of file diff --git a/resources/assets/sass/_forms.scss b/resources/assets/sass/_forms.scss index 5472e3053..f6b4a3d8a 100644 --- a/resources/assets/sass/_forms.scss +++ b/resources/assets/sass/_forms.scss @@ -45,6 +45,12 @@ input[type="text"], input[type="number"], input[type="email"], input[type="searc margin-bottom: $-s; } +.form-group { + .text-pos, .text-neg { + padding: $-xs 0; + } +} + .inline-input-style { border: 2px dotted #BBB; display: block; diff --git a/resources/assets/sass/_text.scss b/resources/assets/sass/_text.scss index f09c57121..a542da8a1 100644 --- a/resources/assets/sass/_text.scss +++ b/resources/assets/sass/_text.scss @@ -82,7 +82,7 @@ hr { &.faded { background-image: linear-gradient(to right, #FFF, #e3e0e0 20%, #e3e0e0 80%, #FFF); } - &.margin-top { + &.margin-top, &.even { margin-top: $-l; } } @@ -227,4 +227,11 @@ ul { .list > * { display: block; +} + +/** + * Icons + */ +i { + padding-right: $-xs; } \ No newline at end of file diff --git a/resources/assets/sass/image-manager.scss b/resources/assets/sass/image-manager.scss index 15976e733..fc2d2f368 100644 --- a/resources/assets/sass/image-manager.scss +++ b/resources/assets/sass/image-manager.scss @@ -1,6 +1,5 @@ .image-manager-body { - background-color: rgb(37, 37, 37); - max-width: 90%; + background-color: #FFF; max-height: 90%; width: 90%; height: 90%; @@ -9,18 +8,7 @@ border-radius: 4px; box-shadow: 0 0 15px 0 rgba(0, 0, 0, 0.3); overflow: hidden; - .image-manager-list img { - border-radius: 0; - float: left; - margin: 0; - cursor: pointer; - width: 150px; - height: 150px; - border: 1px solid transparent; - &.selected { - border: 3px solid #EEE; - } - } + max-width: 1340px; position: fixed; top: 0; bottom: 0; @@ -28,34 +16,48 @@ z-index: 999; display: flex; p, h1, h2, h3, h4, label, input { - color: #EEE; + color: #444; } h1, h2, h3 { font-weight: 300; } } #image-manager .dropzone-container { - height: 100px; position: relative; + border: 3px dashed #DDD; } -#container { - height: 90vh; +.image-manager-bottom { + position: absolute; + bottom: 0; + right: 0; } +.image-manager-list img { + display: block; + border-radius: 0; + float: left; + margin: 0; + cursor: pointer; + width: (100%/6); + height: auto; + border: 1px solid #FFF; + transition: all cubic-bezier(.4,0,1,1) 160ms; + &.selected { + transform: scale3d(0.92, 0.92, 0.92); + } +} #image-manager .load-more { - width: 150px; - height: 150px; display: block; - float: left; text-align: center; - background-color: #404040; - margin: 1px; - color: #FFF; - line-height: 140px; + background-color: #EEE; + padding: $-s $-m; + color: #AAA; + clear: both; font-size: 20px; cursor: pointer; + font-style: italic; } .image-manager-sidebar { @@ -75,6 +77,7 @@ .image-manager-list { overflow-y: scroll; flex: 1; + border-top: 1px solid #ddd; } .image-manager-content { @@ -93,19 +96,13 @@ * Copyright (c) 2012 Matias Meno */ .dz-message { - font-size: 1.6em; + font-size: 1.4em; font-style: italic; color: #aaa; text-align: center; - line-height: 90px; cursor: pointer; + padding: $-xl $-m; transition: all ease-in-out 120ms; - position: absolute; - top: 0; - left: 50%; - max-width: 400px; - width: 400px; - margin-left: -200px; } .dz-drag-hover .dz-message { background-color: rgb(16, 126, 210); @@ -131,22 +128,10 @@ transform: translateY(0px); } } @keyframes pulse { 0% { - -webkit-transform: scale(1); - -moz-transform: scale(1); - -ms-transform: scale(1); - -o-transform: scale(1); transform: scale(1); } 10% { - -webkit-transform: scale(1.1); - -moz-transform: scale(1.1); - -ms-transform: scale(1.1); - -o-transform: scale(1.1); transform: scale(1.1); } 20% { - -webkit-transform: scale(1); - -moz-transform: scale(1); - -ms-transform: scale(1); - -o-transform: scale(1); transform: scale(1); } } .dropzone, .dropzone * { box-sizing: border-box; } @@ -171,10 +156,6 @@ .dz-preview.dz-image-preview { background: white; } .dz-preview.dz-image-preview .dz-details { - -webkit-transition: opacity 0.2s linear; - -moz-transition: opacity 0.2s linear; - -ms-transition: opacity 0.2s linear; - -o-transition: opacity 0.2s linear; transition: opacity 0.2s linear; } .dz-preview .dz-remove { font-size: 14px; @@ -217,12 +198,6 @@ padding: 0 0.4em; border-radius: 3px; } .dz-preview:hover .dz-image img { - -webkit-transform: scale(1.05, 1.05); - -moz-transform: scale(1.05, 1.05); - -ms-transform: scale(1.05, 1.05); - -o-transform: scale(1.05, 1.05); - transform: scale(1.05, 1.05); - -webkit-filter: blur(8px); filter: blur(8px); } .dz-preview .dz-image { border-radius: 4px; diff --git a/resources/assets/sass/styles.scss b/resources/assets/sass/styles.scss index 7d23045bb..c7301336f 100644 --- a/resources/assets/sass/styles.scss +++ b/resources/assets/sass/styles.scss @@ -8,6 +8,7 @@ @import "buttons"; @import "forms"; @import "tables"; +@import "animations"; @import "tinymce"; @import "image-manager"; diff --git a/resources/views/pages/image-manager.blade.php b/resources/views/pages/image-manager.blade.php index c68434d7b..1a3897811 100644 --- a/resources/views/pages/image-manager.blade.php +++ b/resources/views/pages/image-manager.blade.php @@ -3,19 +3,42 @@