diff --git a/.gitignore b/.gitignore index 59e8f45..4519587 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,13 @@ /node_modules /public/hot /public/storage + +public/uploads/* +!public/uploads/.gitkeep + +/public/medias/* +!public/medias/.gitkeep + /storage/*.key /vendor .env diff --git a/app/Http/Controllers/MediaController.php b/app/Http/Controllers/MediaController.php index b3f3691..842b930 100644 --- a/app/Http/Controllers/MediaController.php +++ b/app/Http/Controllers/MediaController.php @@ -35,9 +35,9 @@ class MediaController extends Controller $limit = $request->input('limit'); if($dossier_id == "0"){ - $response['data'] = Media::where('sujet_id', $sujet_id)->whereNull('dossier_id')->offset($offset)->limit($limit)->get(); + $response['data'] = Media::where('sujet_id', $sujet_id)->whereNull('dossier_id')->offset($offset)->limit($limit)->orderBy('created_at', 'desc')->get(); }else{ - $response['data'] = Media::where('sujet_id', $sujet_id)->where('dossier_id', $dossier_id)->offset($offset)->limit($limit)->get(); + $response['data'] = Media::where('sujet_id', $sujet_id)->where('dossier_id', $dossier_id)->offset($offset)->limit($limit)->orderBy('created_at', 'desc')->get(); } return json_encode($response); diff --git a/app/Http/Controllers/UploadController.php b/app/Http/Controllers/UploadController.php new file mode 100644 index 0000000..fe3170d --- /dev/null +++ b/app/Http/Controllers/UploadController.php @@ -0,0 +1,164 @@ +input('uid'); + $sujet_id = $request->input('sujet_id'); + $dossier_id = $request->input('dossier_id'); + if($dossier_id == 0) $dossier_id = null; + + $headers = $request->headers->all(); + $acceptFileTypes = array('gif','jpeg', 'jpg','png','mp4','mp3','psd','ai','eps','svg','indd','pdf'); + + if ($request->hasFile('files')) { + $file = $request->file('files'); + + foreach($file as $files){ + $is_last_chunk = false; + $is_chunked_upload = !empty($headers['content-range']); + if ($is_chunked_upload) { + if (preg_match('|(\d+)/(\d+)|', $headers['content-range'][0], $range)) { + if ($range[1] == $range[2] - 1) { + $is_last_chunk = true; + } + } + } + + $extension = strtolower($files->getClientOriginalExtension()); + if (!in_array($extension, $acceptFileTypes)) return array("false"); + + if($is_chunked_upload){ + $filename = $uid."_".$range[1].".".$extension; + }else{ + $filename = $uid.'.'.$extension; + } + + $uploadPath = public_path() . '/uploads/'; + $files->move($uploadPath, $filename); + + // si c'est le dernier morceux d'un fichier + if($is_last_chunk){ + if($dossier = opendir($uploadPath)){ + $dirFiles = array(); + // on compile tous les chunk du fichier + while(false !== ($fichier = readdir($dossier))){ + if($fichier != '.' && $fichier != '..' ){ + if(strpos($fichier,$uid) !== false){ + $dirFiles[$fichier] = str_replace(".".$extension, "", str_replace($uid."_", "", $fichier)); + } + } + } + closedir($dossier); + // on les trie pour les assembler dans le bon ordre + asort ($dirFiles, SORT_NUMERIC ); + // on les assemble dans un fichier final + $filename = $uid . '.' . $extension; + foreach($dirFiles as $key => $fichier) { + $file = fopen($uploadPath.$key, 'rb'); + $buff = fread($file, filesize($uploadPath.$key)); + fclose($file); + + $final = fopen($uploadPath.$filename, 'a'); + $write = fwrite($final, $buff); + fclose($final); + + unlink($uploadPath.$key); + } + + + } + } + + // si c'est le dernier morceau d'un fichier ou que c'est un envoi simple + if($is_last_chunk || !$is_chunked_upload ){ + + // On déplace le fichier dans le répertoire des médias + $destinationPath = $this->get_mediaFolder()."/"; + Storage::move("uploads/".$filename, $destinationPath.$filename); + + // on créé un média en bdd + $media = new Media(); + $media->libelle = $filename; + $media->extension = $extension; + $media->source = $destinationPath.$filename; + $media->taille = $this->formatBytes($this->get_file_size($destinationPath.$filename)); + + switch ($extension) { + // Photo (1) + case 'gif': + case 'jpeg': + case 'jpg': + case 'png': + $media->typemedia_id = 1; + list($width, $height) = getimagesize($destinationPath.$filename); + $media->largeur = $width; + $media->hauteur = $height; + $media->resolution = $this->get_dpi($destinationPath.$filename); + $this->createThumbnail($destinationPath.$filename, $destinationPath.$uid.'_thumb.'.$extension, 200); + break; + // Illustration/Vectorielle (2) + case 'ai': + case 'svg': + $media->typemedia_id = 2; + break; + // Vidéo (3) + case 'mp4': + $media->typemedia_id =3 ; + $getID3 = new \getID3; + if($fileInfo = $getID3->analyze($destinationPath.$filename)){ + $media->largeur = $fileInfo['video']['resolution_x']; + $media->hauteur = $fileInfo['video']['resolution_y']; + $media->duree = $fileInfo['playtime_string']; + } + break; + // Audio (4) + case 'mp3': + $media->typemedia_id = 4; + $getID3 = new \getID3; + if($fileInfo = $getID3->analyze($destinationPath.$filename)){ + $media->duree= $fileInfo['playtime_string']; + } + break; + // Document (5) + case 'eps': + case 'indd': + case 'pdf': + case 'psd': + default: + $media->typemedia_id = 5; + break; + } + + + $media->dossier_id = $dossier_id; + $media->sujet_id = $sujet_id; + $media->save(); + } + + $filest = array(); + $filest['name'] = $filename; + $filest['uid'] = $uid; + $filesa['files'][]=$filest; + } + return $filesa; + } + } + +} diff --git a/app/Http/Traits/MediaTools.php b/app/Http/Traits/MediaTools.php new file mode 100644 index 0000000..c18ab81 --- /dev/null +++ b/app/Http/Traits/MediaTools.php @@ -0,0 +1,221 @@ +fix_integer_overflow(filesize($file_path)); + } + + public function get_mediaFolder() { + $mediaPath = "medias/"; + $directories = Storage::allDirectories($mediaPath ); + $selectedFolder = ""; + + // on obtient le dernier dossier créé + foreach ($directories as $key => $foldername) { + if($selectedFolder < $foldername){ + $selectedFolder = $foldername; + } + } + // si on n'a pas de dossier, on le créé + if($selectedFolder == ""){ + $selectedFolder = $mediaPath.uniqid(); + Storage::makeDirectory($selectedFolder); + }else{ + // on compte le nombre de fichier + $files = Storage::allFiles($selectedFolder); + // si on en a plus de 1000, on créé un nouveau dossier + if(count($files)> 1000){ + $selectedFolder = $mediaPath.uniqid(); + Storage::makeDirectory($selectedFolder); + } + } + return $selectedFolder; + } + + public function fix_integer_overflow($size) { + if ($size < 0) { + $size += 2.0 * (PHP_INT_MAX + 1); + } + return $size; + } + + public function formatBytes($octet, $precision = 2) { + // Array contenant les differents unités + $unite = array('octet','Ko','Mo','Go'); + + if ($octet < 1000) // octet + { + return $octet.$unite[0]; + } + else + { + if ($octet < 1000000) // ko + { + $ko = round($octet/1024,2); + return $ko.$unite[1]; + } + else // Mo ou Go + { + if ($octet < 1000000000) // Mo + { + $mo = round($octet/(1024*1024),2); + return $mo.$unite[2]; + } + else // Go + { + $go = round($octet/(1024*1024*1024),2); + return $go.$unite[3]; + } + } + } + } + + public function get_dpi($filename){ + + // open the file and read first 20 bytes. + $a = fopen($filename,'r'); + $string = fread($a,20); + fclose($a); + + // get the value of byte 14th up to 18th + $data = bin2hex(substr($string,14,4)); + $x = substr($data,0,4); + $y = substr($data,4,4); + //return array(hexdec($x),hexdec($y)); + return hexdec($x); + } + + + /** + * @param $src - a valid file location + * @param $dest - a valid file target + * @param $targetWidth - desired output width + * @param $targetHeight - desired output height or null + */ + function createThumbnail($src, $dest, $targetWidth, $targetHeight = null) { + + + + // Link image type to correct image loader and saver + // - makes it easier to add additional types later on + // - makes the function easier to read + $IMAGETYPE_JPEG = 2; + $IMAGETYPE_PNG = 3; + $IMAGETYPE_GIF = 1; + $IMAGE_HANDLERS = [ + 2 => [ + 'load' => 'imagecreatefromjpeg', + 'save' => 'imagejpeg', + 'quality' => 100 + ], + 3 => [ + 'load' => 'imagecreatefrompng', + 'save' => 'imagepng', + 'quality' => 0 + ], + 1 => [ + 'load' => 'imagecreatefromgif', + 'save' => 'imagegif' + ] + ]; + + // 1. Load the image from the given $src + // - see if the file actually exists + // - check if it's of a valid image type + // - load the image resource + + // get the type of the image + // we need the type to determine the correct loader + $type = exif_imagetype($src); + + // if no valid type or no handler found -> exit + if (!$type || !$IMAGE_HANDLERS[$type]) { + return null; + } + + // load the image with the correct loader + $image = call_user_func($IMAGE_HANDLERS[$type]['load'], $src); + + // no image found at supplied location -> exit + if (!$image) { + return null; + } + + + // 2. Create a thumbnail and resize the loaded $image + // - get the image dimensions + // - define the output size appropriately + // - create a thumbnail based on that size + // - set alpha transparency for GIFs and PNGs + // - draw the final thumbnail + + // get original image width and height + $width = imagesx($image); + $height = imagesy($image); + + // maintain aspect ratio when no height set + if ($targetHeight == null) { + + // get width to height ratio + $ratio = $width / $height; + + // if is portrait + // use ratio to scale height to fit in square + if ($width > $height) { + $targetHeight = floor($targetWidth / $ratio); + } + // if is landscape + // use ratio to scale width to fit in square + else { + $targetHeight = $targetWidth; + $targetWidth = floor($targetWidth * $ratio); + } + } + + // create duplicate image based on calculated target size + $thumbnail = imagecreatetruecolor($targetWidth, $targetHeight); + + // set transparency options for GIFs and PNGs + if ($type == $IMAGETYPE_GIF || $type == $IMAGETYPE_PNG) { + + // make image transparent + imagecolortransparent( + $thumbnail, + imagecolorallocate($thumbnail, 0, 0, 0) + ); + + // additional settings for PNGs + if ($type == $IMAGETYPE_PNG) { + imagealphablending($thumbnail, false); + imagesavealpha($thumbnail, true); + } + } + + // copy entire source image to duplicate image and resize + imagecopyresampled( + $thumbnail, + $image, + 0, 0, 0, 0, + $targetWidth, $targetHeight, + $width, $height + ); + + + // 3. Save the $thumbnail to disk + // - call the correct save method + // - set the correct quality level + + // save the duplicate version of the image to disk + return call_user_func( + $IMAGE_HANDLERS[$type]['save'], + $thumbnail, + $dest, + $IMAGE_HANDLERS[$type]['quality'] + ); + } + +} diff --git a/app/Media.php b/app/Media.php index 7cdc749..d992fd8 100644 --- a/app/Media.php +++ b/app/Media.php @@ -23,4 +23,12 @@ class Media extends Model { return $this->belongsTo('App\Sujet', 'sujet_id'); } + + /** + * Get the typemedia that owns the media. + */ + public function typemedia() + { + return $this->belongsTo('App\Typemedia', 'typemedia_id'); + } } diff --git a/app/Typemedia.php b/app/Typemedia.php new file mode 100644 index 0000000..2a23f2e --- /dev/null +++ b/app/Typemedia.php @@ -0,0 +1,15 @@ +=5.3.0" + }, + "require-dev": { + "jakub-onderka/php-parallel-lint": "^0.9 || ^1.0" + }, + "suggest": { + "ext-SimpleXML": "SimpleXML extension is required to analyze RIFF/WAV/BWF audio files (also requires `ext-libxml`).", + "ext-com_dotnet": "COM extension is required when loading files larger than 2GB on Windows.", + "ext-ctype": "ctype extension is required when loading files larger than 2GB on 32-bit PHP (also on 64-bit PHP on Windows) or executing `getid3_lib::CopyTagsToComments`.", + "ext-dba": "DBA extension is required to use the DBA database as a cache storage.", + "ext-exif": "EXIF extension is required for graphic modules.", + "ext-iconv": "iconv extension is required to work with different character sets (when `ext-mbstring` is not available).", + "ext-json": "JSON extension is required to analyze Apple Quicktime videos.", + "ext-libxml": "libxml extension is required to analyze RIFF/WAV/BWF audio files.", + "ext-mbstring": "mbstring extension is required to work with different character sets.", + "ext-mysql": "MySQL extension is required to use the MySQL database as a cache storage (deprecated in PHP 5.5, removed in PHP >= 7.0, use `ext-mysqli` instead).", + "ext-mysqli": "MySQLi extension is required to use the MySQL database as a cache storage.", + "ext-rar": "RAR extension is required for RAR archive module.", + "ext-sqlite3": "SQLite3 extension is required to use the SQLite3 database as a cache storage.", + "ext-xml": "XML extension is required for graphic modules to analyze the XML metadata.", + "ext-zlib": "Zlib extension is required for archive modules and compressed metadata." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9.x-dev" + } + }, + "autoload": { + "classmap": [ + "getid3/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-1.0-or-later", + "LGPL-3.0-only", + "MPL-2.0" + ], + "description": "PHP script that extracts useful information from popular multimedia file formats", + "homepage": "https://www.getid3.org/", + "keywords": [ + "codecs", + "php", + "tags" + ], + "time": "2019-02-07T17:30:03+00:00" + }, { "name": "laravel/framework", "version": "v5.8.2", diff --git a/config/filesystems.php b/config/filesystems.php index 77fa5de..910571a 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -45,7 +45,7 @@ return [ 'local' => [ 'driver' => 'local', - 'root' => storage_path('app'), + 'root' => public_path(), ], 'public' => [ diff --git a/public/css/app.css b/public/css/app.css index 0ea5a63..fc98168 100644 --- a/public/css/app.css +++ b/public/css/app.css @@ -154,6 +154,21 @@ table { box-sizing: inherit; } +.group:before, +.group:after { + content: ""; + display: table; +} + +.group:after { + clear: both; +} + +.group { + zoom: 1; + /* For IE 6/7 (trigger hasLayout) */ +} + /*! * animate.css -http://daneden.me/animate * Version - 3.7.0 @@ -12191,6 +12206,183 @@ readers do not read off random characters that represent icons */ font-family: "Font Awesome 5 Brands"; } +/* + * jQuery File Upload Plugin CSS + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2013, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * https://opensource.org/licenses/MIT + */ + +.upload_container { + display: none; + position: absolute; + top: 50%; + left: 50%; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + width: 300px; + height: 400px; + background-color: #ffffff; + z-index: 100; + border-radius: 10px; + /* Fixes for IE < 8 */ +} + +.upload_container .fileinput-button { + position: relative; + overflow: hidden; + display: inline-block; + margin-bottom: 0; + font-size: 14px; + font-weight: 400; + line-height: 1.42857143; + text-align: left; + white-space: nowrap; + vertical-align: middle; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; + width: 100%; + font-size: 15px; + color: #3b3b3b; + padding: 16px; + cursor: pointer; + border-bottom: 1px solid #aaaaaa; +} + +.upload_container .fileinput-button i { + color: #2489D1; + font-size: 18px; + margin-right: 10px; +} + +.upload_container .fileinput-button input { + position: absolute; + top: 0; + right: 0; + margin: 0; + opacity: 0; + font-size: 200px !important; + direction: ltr; + cursor: pointer; +} + +@media screen\9 { + .upload_container .fileinput-button input { + filter: alpha(opacity=0); + font-size: 100%; + height: 100%; + } +} + +.upload_container .progress { + display: none; + height: 6px; + overflow: hidden; + background-color: #f5f5f5; + position: absolute; + top: 0px; + left: 0; + z-index: 999999999999; + width: 100%; +} + +.upload_container .progress .progress-bar { + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #337ab7; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); + transition: width 0.6s ease; +} + +.upload_container .progress .progress-bar.progress-bar-success { + background-color: #5cb85c; +} + +.upload_container .content_wrapper { + height: 286px; + overflow-y: auto; +} + +.upload_container #files > div { + width: 100%; + padding: 10px; + border-bottom: 1px solid #e8ebed; +} + +.upload_container #files > div div:first-child { + color: #000000; + margin-bottom: 5px; + font-size: 14px; + position: relative; +} + +.upload_container #files > div div:first-child span { + white-space: nowrap; + display: block; + text-overflow: ellipsis; + overflow: hidden; + max-width: 91%; +} + +.upload_container #files > div div:last-child { + color: #3b3b3b; +} + +.upload_container #files > div button { + display: none; + border: none; + background-color: transparent; + position: absolute; + right: 0; + top: -3px; + cursor: pointer; +} + +.upload_container #files > div button i { + color: #337ab7; + font-size: 19px; +} + +.upload_container #files > div:hover button { + display: block; +} + +.upload_container .upload_bar { + border-top: 1px solid #aaaaaa; + width: 100%; + height: 60px; + position: absolute; + bottom: 0; + padding: 13px 10px; +} + +.upload_container .upload_bar #submit { + display: inline-block; +} + +.upload_container .upload_bar #cancel, +.upload_container .upload_bar #close_upload_form { + color: #3b3b3b; + cursor: pointer; + margin-left: 15px; +} + /****************************************** HEADER ******************************************/ @@ -12502,6 +12694,47 @@ readers do not read off random characters that represent icons */ width: 100%; } +/****************************************** + UPLOADER +******************************************/ + +.uploader-window { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 86, 132, 0.9); + z-index: 250000; + display: none; + text-align: center; +} + +.uploader-window .uploader-window-content { + position: absolute; + top: 10px; + left: 10px; + right: 10px; + bottom: 10px; + border: 1px dashed #fff; + pointer-events: none; +} + +.uploader-window .uploader-window-content h1 { + margin: -0.5em 0 0; + position: absolute; + font-weight: bold; + top: 50%; + left: 0; + right: 0; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + font-size: 37px; + color: #fff; + padding: 0; + pointer-events: none; +} + /****************************************** SIDE MENU ******************************************/ @@ -12850,12 +13083,6 @@ h1 { display: inline-block; } -.group:after { - content: ""; - display: table; - clear: both; -} - .filter_row { margin-bottom: 10px; } @@ -13030,12 +13257,66 @@ table tfoot tr { min-height: 129px; } +.media_manager .main_content header .search_wrapper .search_filters { + display: inline-flex; + align-items: center; + padding: 0px 10px; +} + +.media_manager .main_content header .search_wrapper .search_filters > div { + display: flex; + align-items: center; + margin-right: 10px; +} + +.media_manager .main_content header .search_wrapper .search_filters > div i { + margin-left: 10px; +} + .media_manager .main_content header .action_wrapper { background-color: #3b3b3b; width: 100%; min-height: 45px; } +.media_manager .main_content header .action_wrapper a { + font-size: 14px; + padding: 15px 20px; + display: inline-block; + border-right: 1px solid #505050; + float: left; + transition: 0.3s ease-in-out; +} + +.media_manager .main_content header .action_wrapper a:hover { + background-color: #333333; +} + +.media_manager .main_content header .action_wrapper a i { + background-color: #000000; + border-radius: 20px; + margin-right: 5px; + padding: 5px 6px; + font-size: 11px; + color: #ffffff; +} + +.media_manager .main_content header .action_wrapper a.action_download_media i { + background-color: #f6993f; +} + +.media_manager .main_content header .action_wrapper a.action_add_basket i { + background-color: #4dc0b5; +} + +.media_manager .main_content header .action_wrapper a.action_delete_media i { + background-color: #e3342f; +} + +.media_manager .main_content header .action_wrapper a.action_tag_media i { + background-color: #6cb2eb; +} + .media_manager .main_content .scrollLoader { position: absolute; border-bottom: 0; @@ -13082,21 +13363,147 @@ table tfoot tr { top: 0; } -.media_manager .main_content .media_container .imageItem { - padding: 51px 20px; - margin: 30px 10px; +.media_manager .main_content .media_container .wrapper { + display: flex; + flex-wrap: wrap; +} + +.media_manager .main_content .media_container .wrapper .imageItem { display: inline-block; border: 1px solid grey; + width: 202px; + margin: 8px 10px; + background-color: #333333; + transition: 0.3s ease-in-out; + position: relative; + padding-bottom: 25px; + cursor: pointer; } -.media_manager .main_content .media_container .imageItem[aria-grabbed=true] { - background: #8ad; - color: #fff; +.media_manager .main_content .media_container .wrapper .imageItem .contextMenu { + position: absolute; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.7); + left: 0px; + top: 0px; + z-index: 2; + display: none; + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); + color: #ffffff; + justify-content: center; + align-items: center; } -.media_manager .main_content .media_container .imageItem:focus { - outline: none; - box-shadow: 0 0 0 2px #68b, inset 0 0 0 1px #ddd; +.media_manager .main_content .media_container .wrapper .imageItem .contextMenu .menu-option { + padding: 10px; + transition: 0.3s ease-in-out; +} + +.media_manager .main_content .media_container .wrapper .imageItem .contextMenu .menu-option i { + margin-right: 5px; +} + +.media_manager .main_content .media_container .wrapper .imageItem .contextMenu .menu-option:hover { + background-color: #2ea8e5; +} + +.media_manager .main_content .media_container .wrapper .imageItem.flip { + -webkit-transform: rotateY(180deg); + transform: rotateY(180deg); +} + +.media_manager .main_content .media_container .wrapper .imageItem.flip .contextMenu { + display: flex; +} + +.media_manager .main_content .media_container .wrapper .imageItem .media { + height: 200px; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + position: relative; +} + +.media_manager .main_content .media_container .wrapper .imageItem .media::before { + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + display: block; + position: absolute; + left: 50%; + top: 50%; + text-align: center; + text-indent: 0; + color: #ffffff; + font-size: 59px; + z-index: 1; +} + +.media_manager .main_content .media_container .wrapper .imageItem .media.video::before { + content: "\F167"; + font-family: "Font Awesome 5 Brands"; +} + +.media_manager .main_content .media_container .wrapper .imageItem .media.son::before { + content: "\F58F"; + font-family: "Font Awesome 5 Pro"; + font-weight: 900; +} + +.media_manager .main_content .media_container .wrapper .imageItem .media.doc::before { + content: "\F15C"; + font-family: "Font Awesome 5 Pro"; + font-weight: 900; +} + +.media_manager .main_content .media_container .wrapper .imageItem .libelle { + padding: 4px; + text-align: center; + color: #ffffff; + margin: 0; + word-wrap: break-word; +} + +.media_manager .main_content .media_container .wrapper .imageItem .info { + position: absolute; + bottom: 0; + padding: 4px; + font-size: 11px; +} + +.media_manager .main_content .media_container .wrapper .imageItem .info i { + margin-right: 7px; +} + +.media_manager .main_content .media_container .wrapper .imageItem[aria-grabbed=true]::before { + content: "\F058"; + font-family: "Font Awesome 5 Pro"; + font-weight: 900; + display: block; + position: absolute; + left: 5px; + top: 5px; + text-align: center; + text-indent: 0; + color: #2489D1; + font-size: 25px; + z-index: 2; +} + +.media_manager .main_content .media_container .wrapper .imageItem[aria-grabbed=true]::after { + content: ""; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + position: absolute; + left: 0px; + top: 0px; + z-index: 1; +} + +.media_manager .main_content .media_container .wrapper .imageItem:hover { + background-color: #3b3b3b; } .media_manager [draggable] { @@ -13112,6 +13519,7 @@ table tfoot tr { width: 340px; height: 100%; transition: 0.3s ease-in-out; + z-index: 1; } .media_manager .side_menu.collapse { diff --git a/public/js/app.js b/public/js/app.js index c99d66f..33599dd 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -11090,6 +11090,7 @@ $(document).ready(function () { $("#sujet_selector").on('change', function (event) { var sujetId = $("#sujet_selector").val(); if (sujetId != "") $('.dd').nestable('destroy'); + $(".currentFolder").val(0); initFolderManager(sujetId); }); // ---- Gestion des média : sélectionner un dossier et favoris @@ -11349,6 +11350,18 @@ $(document).ready(function () { dossier_id: dossier_id, libelle: libelle, description: description + }, + success: function success(result) { + $(".folder_container .dd3-item[data-id='" + dossier_id + "'] > .dd3-content span").html(libelle); + $.fancybox.getInstance().close(); + }, + error: function error(jqXHR, textStatus, errorThrown) { + $.fancybox.getInstance().close(); + $.fancyMessage({ + title: "Attention", + message: "Erreur lors de l'édition du dossier, merci d'actualiser la page.", + type: "error" + }); } }); }); // ---- Gestion des média : au début du drag, set les valeurs des éléments draggés @@ -11370,14 +11383,22 @@ $(document).ready(function () { } }); // ---- Gestion des média : déselectionne les éléments si on clique en dehors - $(".main_content").on("click", function (event) { + $(".main_content .wrapper").on("click", function (event) { if (event.target !== this) return; $(".imageItem").attr("aria-grabbed", "false"); + $(".imageItem").removeClass('flip'); + }); // ---- Gestion des média : déselectionne les éléments si on clique en dehors + + $(".main_content .wrapper").on("contextmenu", '.imageItem', function (event) { + event.preventDefault(); + $(".imageItem").removeClass('flip'); + $(this).addClass('flip'); }); // ---- Gestion des média : gère la sélection des éléments var lastSelected; $("html").on("click", ".imageItem", function (event) { event.preventDefault(); + $(".imageItem").removeClass('flip'); if (event.ctrlKey) { if ($(this).attr("aria-grabbed") == "true") { @@ -11408,11 +11429,10 @@ $(document).ready(function () { imageItem.eq(i).attr("aria-grabbed", select); } } else { - $(".imageItem").attr("aria-grabbed", "false"); - if ($(this).attr("aria-grabbed") == "true") { - $(this).attr("aria-grabbed", "false"); + $(".imageItem").attr("aria-grabbed", "false"); } else { + $(".imageItem").attr("aria-grabbed", "false"); $(this).attr("aria-grabbed", "true"); } @@ -11492,7 +11512,8 @@ $(document).ready(function () { } }); } - }); + }); // ---- Gestion de l'infinite scroll + $(".main_content .media_container").on("scroll resize", function () { if ($(window).data('ajaxready') == false) return; if ($(window).data('noMedia') == true) return; @@ -11504,6 +11525,146 @@ $(document).ready(function () { loadMedia(dossier_id, sujet_id); } }); + $('#close_upload_form').on('click', function (event) { + event.preventDefault(); + $('.upload_container').hide("fast"); + }); + $('.action_add_media').on('click', function (event) { + event.preventDefault(); + $('.upload_container').show("fast"); + }); + + if ($('#fileupload').length) { + $.ajaxSetup({ + headers: { + 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') + } + }); + var cancel_btn = $('