From a65ab11d9fde055b1e94a03916f3ae7b0be14e84 Mon Sep 17 00:00:00 2001 From: Codenift Date: Fri, 25 Oct 2019 10:30:33 -0400 Subject: [PATCH] Upload artwork using drag and drop or click to browse using track edit. --- .../application/common/FileDataHelper.php | 63 +++++++ .../controllers/LibraryController.php | 6 + airtime_mvc/application/forms/EditAudioMD.php | 10 +- .../views/scripts/library/edit-file-md.phtml | 11 +- airtime_mvc/public/css/styles.css | 91 ++++++++++ .../public/js/airtime/library/library.js | 156 +++++++++++++++++- 6 files changed, 334 insertions(+), 3 deletions(-) diff --git a/airtime_mvc/application/common/FileDataHelper.php b/airtime_mvc/application/common/FileDataHelper.php index 3c576f685..983885c7e 100644 --- a/airtime_mvc/application/common/FileDataHelper.php +++ b/airtime_mvc/application/common/FileDataHelper.php @@ -251,6 +251,69 @@ class FileDataHelper { return $get_img; } + /** + * Upload artwork + * + * @param string $trackid + * @param string $data + * + * @return string Path to artwork + */ + public static function uploadArtwork($trackid, $data) + { + $file = Application_Model_StoredFile::RecallById($trackid); + $md = $file->getMetadata(); + + $storDir = Application_Model_MusicDir::getStorDir(); + $fp = $storDir->getDirectory(); + + $dbAudioPath = $md["MDATA_KEY_FILEPATH"]; + $fullpath = $fp . $dbAudioPath; + + $base64 = @$data; + $mime = explode(';', $base64)[0]; + + $audioPath = dirname($fullpath); + $dbPath = dirname($dbAudioPath); + $path_parts = pathinfo($fullpath); + $file = $path_parts['filename']; + + //Save Data URI + if (file_put_contents($audioPath . "/" . $file, $base64)) { + $get_img = $dbPath . "/" . $file; + } else { + Logging::error("Could not save Data URI"); + } + + $rfile = $audioPath . "/" . $file; + + if ($mime == "data:image/png") { + $ext = 'png'; + } elseif ($mime == "data:image/gif") { + $ext = 'gif'; + } elseif ($mime == "data:image/bmp") { + $ext = 'bmp'; + } else { + $ext = 'jpg'; + } + + if (file_exists($rfile)) { + self::resizeImage($rfile, $rfile . '-32.jpg', $ext, 32, 100); + self::resizeImage($rfile, $rfile . '-64.jpg', $ext, 64, 100); + self::resizeImage($rfile, $rfile . '-128.jpg', $ext, 128, 100); + self::resizeImage($rfile, $rfile . '-256.jpg', $ext, 256, 100); + self::resizeImage($rfile, $rfile . '-512.jpg', $ext, 512, 100); + self::imgToDataURI($rfile . '-32.jpg', $rfile . '-32'); + self::imgToDataURI($rfile . '-64.jpg', $rfile . '-64'); + self::imgToDataURI($rfile . '-128.jpg', $rfile . '-128'); + self::imgToDataURI($rfile . '-256.jpg', $rfile . '-256'); + } else { + Logging::error("The file $rfile does not exist"); + } + + return $get_img; + } + /** * Render image * Used in API to render JPEG diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php index 28c5f02bb..8033555df 100644 --- a/airtime_mvc/application/controllers/LibraryController.php +++ b/airtime_mvc/application/controllers/LibraryController.php @@ -400,6 +400,12 @@ class LibraryController extends Zend_Controller_Action } else { $serialized[$j["name"]] = $j["value"]; } + + if ($j["name"] == "artwork_uploaded") { + if ($j["value"] != null || $j["value"] != ''){ + $serialized["artwork"] = FileDataHelper::uploadArtwork($file_id, $j["value"] ); + } + } } // Sanitize any wildly incorrect metadata before it goes to be validated. diff --git a/airtime_mvc/application/forms/EditAudioMD.php b/airtime_mvc/application/forms/EditAudioMD.php index 62a83f66c..8b7f40754 100644 --- a/airtime_mvc/application/forms/EditAudioMD.php +++ b/airtime_mvc/application/forms/EditAudioMD.php @@ -22,13 +22,21 @@ class Application_Form_EditAudioMD extends Zend_Form $artwork = new Zend_Form_Element_Hidden('artwork'); $artwork->setFilters(array('StringTrim')) ->setValidators(array( - new Zend_Validate_StringLength(array('max' => 512)) + new Zend_Validate_StringLength(array('max' => 2048)) )); $file_id->addDecorator('HtmlTag', array('tag' => 'div', 'style' => 'display:none')); $file_id->removeDecorator('Label'); $file_id->setAttrib('class', 'artwork'); $this->addElement($artwork); + // Add artwork uploaded hidden field + $artwork_uploaded = new Zend_Form_Element_Hidden('artwork_uploaded'); + $artwork_uploaded->class = 'input_text artwork_uploaded_'. $p_id; + $file_id->addDecorator('HtmlTag', array('tag' => 'div', 'style' => 'display:none')); + $file_id->removeDecorator('Label'); + $file_id->setAttrib('class', 'artwork_uploaded'); + $this->addElement($artwork_uploaded); + // Add title field $track_title = new Zend_Form_Element_Text('track_title'); $track_title->class = 'input_text'; diff --git a/airtime_mvc/application/views/scripts/library/edit-file-md.phtml b/airtime_mvc/application/views/scripts/library/edit-file-md.phtml index 4f09f9db4..03e919d66 100644 --- a/airtime_mvc/application/views/scripts/library/edit-file-md.phtml +++ b/airtime_mvc/application/views/scripts/library/edit-file-md.phtml @@ -19,7 +19,16 @@
- '; ?> +
+
+ + +
+
+
+
+
+
diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css index 981ac5f92..ae9af550a 100644 --- a/airtime_mvc/public/css/styles.css +++ b/airtime_mvc/public/css/styles.css @@ -4284,3 +4284,94 @@ li .ui-state-hover { .track-edit-right { margin-left: 160px; } + +/* Artwork Upload in Tracks Edit */ +.artwork-upload { + position: relative; + max-width: 205px; +} + +.artwork-upload .artwork-edit { + position: absolute; + z-index: 1; + top: 0; +} +.artwork-upload .artwork-edit input { + display: none; +} +.artwork-upload .artwork-edit input + label { + display: inline-block; + width: 140px; + height: 140px; + margin: 1px; + border-radius: 1px; + border: 1px solid transparent; + box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.12); + cursor: pointer; + font-weight: normal; + transition: all 0.2s ease-in-out; +} +.artwork-upload .artwork-edit input + label:hover { + background: rgba(0, 0, 0, 0.40); + border-color: #d6d6d6; +} +.artwork-upload .artwork-edit input + label:after { + color: #757575; + position: absolute; + top: 10px; + left: 0; + right: 0; + text-align: center; + margin: auto; +} +.artwork-upload .artwork-preview { + width: 140px; + height: 140px; + position: relative; + border-radius: 1px; + border: 2px solid #F8F8F8; + box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1); +} +.artwork-upload .artwork-preview > div { + width: 100%; + height: 100%; + background-size: cover; + background-repeat: no-repeat; + background-position: center; +} + +/* Drag and Drop Artwork */ +body.droppable .artwork-upload .artwork-preview { + border: 2px dashed lightblue; + z-index: 9999; +} +.profile { + width: 50%; +} +.profile-avatar-wrap { + width: 33.33%; + float: left; + margin: 0 20px 5px 0; + position: relative; + pointer-events: none; + border: 5px solid transparent; +} +.profile-avatar-wrap:after { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.profile-avatar-wrap img { + width: 100%; + display: block; +} +.location { + text-transform: uppercase; + color: #999; + letter-spacing: 1px; + margin: 0 0 10px 0; + font-size: 90%; +} diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js index 38a675e81..14a1594e7 100644 --- a/airtime_mvc/public/js/airtime/library/library.js +++ b/airtime_mvc/public/js/airtime/library/library.js @@ -1601,6 +1601,70 @@ var validationTypes = { }; +function readArtworkURL(input, id) { + + if (input.files && input.files[0]) { + var reader = new FileReader(); + reader.onload = function(e) { + $('.artwork-preview-'+id).css('background-image', 'url('+e.target.result +')'); + $('.artwork-preview-'+id).hide(); + $('.artwork-preview-'+id).fadeIn(500); + $('.artwork_uploaded_'+id).val(function() { + return e.target.result; + }); + } + reader.readAsDataURL(input.files[0]); + } +} + +// Resample Artwork +var resampleImg = (function (canvas) { + + function resampleImg(img, width, height, onresample) { + var load = typeof img == "string", + i = load || img; + if (load) { + i = new Image; + i.onload = onload; + i.onerror = onerror; + } + i._onresample = onresample; + i._width = width; + i._height = height; + load ? (i.src = img) : onload.call(img); + } + + function onerror() { + throw ("not found: " + this.src); + } + + function onload() { + var img = this, + width = img._width, + height = img._height, + onresample = img._onresample; + + var minValue = Math.min(img.height, img.width); + width == null && (width = round(img.width * height / img.height)); + height == null && (height = round(img.height * width / img.width)); + + delete img._onresample; + delete img._width; + delete img._height; + canvas.width = width; + canvas.height = height; + context.drawImage(img,0,0,minValue,minValue,0,0,width,height); + onresample(canvas.toDataURL("image/jpeg")); + } + + var context = canvas.getContext("2d"), + round = Math.round; + + return resampleImg; + +}(this.document.createElement("canvas"))); + + $(document).ready(function() { if (window.location.href.indexOf("showbuilder") > -1) { AIRTIME.library.initPodcastDatatable(); @@ -1613,5 +1677,95 @@ $(document).ready(function() { $(window).resize(function() { resizeAdvancedSearch(); }); -}); + // image upload by clicking on the artwork container + $(document).on('change', '.artworkUpload', 'input', function(event) { + event.preventDefault(); + event.stopPropagation(); + var id = $(this).attr('data-id'); + readArtworkURL(this, id); + }); + + // image upload by dragging onto the artwork container + $.event.props.push('dataTransfer'); + (function() { + + var s; + var Artwork = { + settings: { + body: $("body") + }, + init: function() { + s = Artwork.settings; + Artwork.bindUIActions(); + }, + bindUIActions: function() { + + var timer; + s.body.on('dragover', '.artwork-upload', function(event) { + + event.preventDefault(); + event.stopPropagation(); + clearTimeout(timer); + Artwork.showDroppableArea(); + return false; + }); + s.body.on('dragleave', '.artwork-upload', function(event) { + + event.preventDefault(); + event.stopPropagation(); + timer = setTimeout(function() { + Artwork.hideDroppableArea(); + }, 200); + }); + s.body.on('drop', '.artwork-upload', function(event) { + event.preventDefault(); + event.stopPropagation(); + var id = $(this).attr('data-id'); + Artwork.handleDrop(event.dataTransfer.files, id); + }); + + }, + showDroppableArea: function() { + s.body.addClass("droppable"); + }, + hideDroppableArea: function() { + s.body.removeClass("droppable"); + }, + handleDrop: function(files, id) { + Artwork.hideDroppableArea(); + var file = files[0]; + if (typeof file !== 'undefined' && file.type.match('image.*')) { + Artwork.resizeImage(file, 512, function(data) { + Artwork.placeImage(data, id); + }); + } else { + alert("The file is not an image."); + } + }, + resizeImage: function(file, size, callback) { + var fileTracker = new FileReader; + fileTracker.onload = function() { + resampleImg(this.result, size, size, callback); + } + fileTracker.readAsDataURL(file); + fileTracker.onabort = function() { + alert("Upload aborted!"); + } + fileTracker.onerror = function() { + alert("File could not be read."); + } + }, + placeImage: function(data, id) { + $('.artwork-preview-'+id).css('background-image', 'url('+ data +')'); + $('.artwork-preview-'+id).hide(); + $('.artwork-preview-'+id).fadeIn(500); + $('.artwork_uploaded_'+id).val(function() { + return data; + }); + } + } + Artwork.init(); + })(); + +});