front : upload des médias

This commit is contained in:
Yann Gonidec 2019-05-29 14:05:54 +02:00
parent ed0038193b
commit 329b79a7cb
27 changed files with 4363 additions and 55 deletions

7
.gitignore vendored
View file

@ -1,6 +1,13 @@
/node_modules
/public/hot
/public/storage
public/uploads/*
!public/uploads/.gitkeep
/public/medias/*
!public/medias/.gitkeep
/storage/*.key
/vendor
.env

View file

@ -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);

View file

@ -0,0 +1,164 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Request;
use App\Media;
use App\Http\Traits\MediaTools;
class UploadController extends Controller {
use MediaTools;
public function index()
{
return view('upload.show');
}
public function storeMedia(Request $request)
{
$uid = $request->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;
}
}
}

View file

@ -0,0 +1,221 @@
<?php
namespace App\Http\Traits;
use Illuminate\Support\Facades\Storage;
trait MediaTools {
public function get_file_size($file_path) {
return $this->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']
);
}
}

View file

@ -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');
}
}

15
app/Typemedia.php Normal file
View file

@ -0,0 +1,15 @@
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Typemedia extends Model
{
/**
* The primary key associated with the table.
*
* @var string
*/
protected $primaryKey = 'CODE_TYPEMEDIA';
}

View file

@ -11,6 +11,7 @@
"php": "^7.1.3",
"adldap2/adldap2-laravel": "^6.0",
"fideloper/proxy": "^4.0",
"james-heinrich/getid3": "^1.9",
"laravel/framework": "5.8.*",
"laravel/tinker": "^1.0",
"laravelcollective/html": "^5.8"

65
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "fa0af3ae376551c7f6bf0ef24731556a",
"content-hash": "6d9372f2cd06715323c09ad8e275337a",
"packages": [
{
"name": "adldap2/adldap2",
@ -565,6 +565,69 @@
"description": "Highlight PHP code in terminal",
"time": "2018-09-29T18:48:56+00:00"
},
{
"name": "james-heinrich/getid3",
"version": "v1.9.17",
"source": {
"type": "git",
"url": "https://github.com/JamesHeinrich/getID3.git",
"reference": "d2e45f2c4f75cc7443e158757ad2d678e318685d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/JamesHeinrich/getID3/zipball/d2e45f2c4f75cc7443e158757ad2d678e318685d",
"reference": "d2e45f2c4f75cc7443e158757ad2d678e318685d",
"shasum": ""
},
"require": {
"php": ">=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",

View file

@ -45,7 +45,7 @@ return [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
'root' => public_path(),
],
'public' => [

438
public/css/app.css vendored
View file

@ -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 {

244
public/js/app.js vendored
View file

@ -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 = $('<button/>').addClass('cancel').html('<i class="fal fa-times"></i>');
var upload_btn = $('<button/>').addClass('upload').css('display', 'none');
$('#submit').on('click', function (event) {
event.preventDefault();
$("#upload_errors").html("");
$('.upload').click(); //click upload buttons and upload all files in the queue
});
$('#cancel').on('click', function (event) {
event.preventDefault();
$('.cancel').click(); //click cancel buttons and remove all files in the queue
$("#upload_errors").html("");
});
$(".uploader-window").on("dragleave", function () {
$(this).stop().fadeOut("fast");
});
var currentfiles = [];
$('#fileupload').fileupload({
url: "/ajax/upload-media",
dataType: 'json',
limitMultiFileUploads: 10,
maxChunkSize: 10000000,
dragover: function dragover(e, data) {
$(".uploader-window").fadeIn("fast");
},
add: function add(e, data) {
data.files = $.map(data.files, function (file, i) {
if ($.inArray(file.name, currentfiles) >= 0) {
$.fancyMessage({
title: "Attention",
message: "Nous ne pouvons pas envoyer plusieurs fichiers du même nom. Veuillez renommer vos fichiers puis essayez à nouveau.",
type: "error"
});
return null;
}
return file;
});
$.each(data.files, function (index, file) {
var uploadErrors = [];
var acceptFileTypes = /^(gif|jpe?g|png|mp4|mp3|psd|ai|eps|svg|indd|pdf)$/i;
if (file.name.split('.').pop().length && !acceptFileTypes.test(file.name.split('.').pop())) {
uploadErrors.push('Ce type de fichier n\'est pas accepté');
}
if (data.originalFiles[0]['size'].length && data.originalFiles[0]['size'] > 5000000) {
uploadErrors.push('La taille du fichier est trop grande.');
}
if (uploadErrors.length > 0) {
alert(uploadErrors.join("\n"));
return false;
}
currentfiles.push($.trim(file.name));
var row = document.createElement('div');
var col1 = document.createElement('div');
var col2 = document.createElement('div');
$(col1).append("<span>" + file.name + "</span>").append(cancel_btn.clone(true).data(data));
$(col2).append("<span>" + file.type + " - " + FileConvertSize(file.size) + "</span>");
$(col2).append(upload_btn.clone(true).data(data));
$(row).append(col1, col2);
$(".files").append(row);
$('.upload').eq(-1).on('click', function () {
data.formData = {
uid: create_UUID(),
sujet_id: $("#sujet_selector").val(),
dossier_id: $(".currentFolder").val()
};
data.submit();
});
$('.cancel').eq(-1).on('click', function () {
$(this).parent().parent().remove();
currentfiles = arrayRemove(currentfiles, $.trim(file.name));
});
});
},
start: function start(e, data) {
$('#progress').show();
},
drop: function drop(e, data) {
$(".uploader-window").stop().fadeOut("fast");
},
done: function done(e, data) {
$.each(data.files, function (index, file) {
currentfiles = arrayRemove(currentfiles, $.trim(file.name));
}); //---- Chargement des médias
var currentFolder = $(".currentFolder").val();
if (currentFolder == 0 || currentFolder == "") {
var count = $(".folder_container .root_folder .count");
} else {
var count = $(".folder_container .dd3-item[data-id='" + currentFolder + "'] > .dd3-content .count");
}
count.html(parseInt(count.html()) + data.files.length);
},
stop: function stop(e) {
$(".files").html("");
currentfiles = [];
$('#progress .progress-bar').css('width', '0%');
$('#progress').hide();
$('.upload_container').hide("fast");
var currentFolder = $(".currentFolder").val();
if (currentFolder == 0 || currentFolder == "") {
$(".root_folder").trigger("click");
} else {
$('.dd .dd-item[data-id="' + currentFolder + '"] > .dd3-content').trigger("click");
}
},
fail: function fail(e, data) {
$.each(data.files, function (index, file) {
$('<p style="color: red;">Erreur durant le transfert du fichier ' + file.name + '.</p>').appendTo('#upload_errors');
currentfiles = arrayRemove(currentfiles, $.trim(file.name));
});
},
progressall: function progressall(e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css('width', progress + '%');
}
}).prop('disabled', !$.support.fileInput).parent().addClass($.support.fileInput ? undefined : 'disabled');
}
}); // ---- Gestion des média : init des dossiers
function initFolderManager(sujetId) {
@ -11637,9 +11798,51 @@ function loadMedia(dossier_id, sujet_id) {
}
$.each(data, function (index, item) {
output += '<a class="imageItem" data-id="' + item.id + '" href="#" draggable="true" aria-grabbed="false">Mon image';
output += item.libelle;
output += '</a>';
var ico = "";
var detail = "";
var itemClass = "";
var thumb = "";
switch (item.typemedia_id) {
case 1:
case 2:
ico = '<i class="fas fa-file-image"></i>';
detail = " - " + item.largeur + "x" + item.hauteur + "px";
thumb = item.source.split('.')[0] + "_thumb." + item.extension;
break;
case 3:
ico = '<i class="fas fa-file-video"></i>';
detail = " - durée " + item.duree;
itemClass = "video";
break;
case 4:
ico = '<i class="fas fa-file-audio"></i>';
detail = " - durée " + item.duree;
itemClass = "son";
break;
case 5:
ico = '<i class="fas fa-file"></i>';
itemClass = "doc";
break;
default:
}
output += '<div class="imageItem" data-id="' + item.id + '" draggable="true" aria-grabbed="false">';
output += '<div class="contextMenu"><ul>';
output += '<li class="menu-option editItem"><i class="fas fa-edit"></i> Editer</li>';
output += '<li class="menu-option downloadItem"><i class="fas fa-file-download"></i> Télécharger</li>';
output += '<li class="menu-option addBasket"><i class="fas fa-shopping-basket"></i> Ajouter au panier</li>';
output += '<li class="menu-option deleteItem"><i class="fas fa-trash-alt"></i> Supprimer</li>';
output += '<li class="menu-option tagItem"><i class="fas fa-tags"></i> Etiquette</li>';
output += '</ul></div>';
output += '<div class="media ' + itemClass + '" style="background-image:url(' + thumb + ')"></div>';
output += '<p class="libelle">' + item.libelle + '</p>';
output += '<div class="info">' + ico + item.extension + ' - ' + item.taille + detail + '</div>';
output += '</div>';
});
$('.media_container .wrapper').append(output);
@ -11699,6 +11902,31 @@ function addItem(parent_id, item_id, content) {
$('.dd .dd-item[data-id="' + parent_id + '"] > ol').append(html);
}
function arrayRemove(arr, value) {
return arr.filter(function (ele) {
return ele != value;
});
}
function FileConvertSize(aSize) {
aSize = Math.abs(parseInt(aSize, 10));
var def = [[1, 'octets'], [1024, 'ko'], [1024 * 1024, 'Mo'], [1024 * 1024 * 1024, 'Go'], [1024 * 1024 * 1024 * 1024, 'To']];
for (var i = 0; i < def.length; i++) {
if (aSize < def[i][0]) return (aSize / def[i - 1][0]).toFixed(2) + ' ' + def[i - 1][1];
}
}
function create_UUID() {
var dt = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = (dt + Math.random() * 16) % 16 | 0;
dt = Math.floor(dt / 16);
return (c == 'x' ? r : r & 0x3 | 0x8).toString(16);
});
return uuid;
}
/***/ }),
/***/ "./resources/sass/app.scss":

1502
public/js/uploadfile/jquery.fileupload.js vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,224 @@
/*
* jQuery Iframe Transport Plugin
* https://github.com/blueimp/jQuery-File-Upload
*
* Copyright 2011, Sebastian Tschan
* https://blueimp.net
*
* Licensed under the MIT license:
* https://opensource.org/licenses/MIT
*/
/* global define, require, window, document, JSON */
;(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// Register as an anonymous AMD module:
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS:
factory(require('jquery'));
} else {
// Browser globals:
factory(window.jQuery);
}
}(function ($) {
'use strict';
// Helper variable to create unique names for the transport iframes:
var counter = 0,
jsonAPI = $,
jsonParse = 'parseJSON';
if ('JSON' in window && 'parse' in JSON) {
jsonAPI = JSON;
jsonParse = 'parse';
}
// The iframe transport accepts four additional options:
// options.fileInput: a jQuery collection of file input fields
// options.paramName: the parameter name for the file form data,
// overrides the name property of the file input field(s),
// can be a string or an array of strings.
// options.formData: an array of objects with name and value properties,
// equivalent to the return data of .serializeArray(), e.g.:
// [{name: 'a', value: 1}, {name: 'b', value: 2}]
// options.initialIframeSrc: the URL of the initial iframe src,
// by default set to "javascript:false;"
$.ajaxTransport('iframe', function (options) {
if (options.async) {
// javascript:false as initial iframe src
// prevents warning popups on HTTPS in IE6:
/*jshint scripturl: true */
var initialIframeSrc = options.initialIframeSrc || 'javascript:false;',
/*jshint scripturl: false */
form,
iframe,
addParamChar;
return {
send: function (_, completeCallback) {
form = $('<form style="display:none;"></form>');
form.attr('accept-charset', options.formAcceptCharset);
addParamChar = /\?/.test(options.url) ? '&' : '?';
// XDomainRequest only supports GET and POST:
if (options.type === 'DELETE') {
options.url = options.url + addParamChar + '_method=DELETE';
options.type = 'POST';
} else if (options.type === 'PUT') {
options.url = options.url + addParamChar + '_method=PUT';
options.type = 'POST';
} else if (options.type === 'PATCH') {
options.url = options.url + addParamChar + '_method=PATCH';
options.type = 'POST';
}
// IE versions below IE8 cannot set the name property of
// elements that have already been added to the DOM,
// so we set the name along with the iframe HTML markup:
counter += 1;
iframe = $(
'<iframe src="' + initialIframeSrc +
'" name="iframe-transport-' + counter + '"></iframe>'
).bind('load', function () {
var fileInputClones,
paramNames = $.isArray(options.paramName) ?
options.paramName : [options.paramName];
iframe
.unbind('load')
.bind('load', function () {
var response;
// Wrap in a try/catch block to catch exceptions thrown
// when trying to access cross-domain iframe contents:
try {
response = iframe.contents();
// Google Chrome and Firefox do not throw an
// exception when calling iframe.contents() on
// cross-domain requests, so we unify the response:
if (!response.length || !response[0].firstChild) {
throw new Error();
}
} catch (e) {
response = undefined;
}
// The complete callback returns the
// iframe content document as response object:
completeCallback(
200,
'success',
{'iframe': response}
);
// Fix for IE endless progress bar activity bug
// (happens on form submits to iframe targets):
$('<iframe src="' + initialIframeSrc + '"></iframe>')
.appendTo(form);
window.setTimeout(function () {
// Removing the form in a setTimeout call
// allows Chrome's developer tools to display
// the response result
form.remove();
}, 0);
});
form
.prop('target', iframe.prop('name'))
.prop('action', options.url)
.prop('method', options.type);
if (options.formData) {
$.each(options.formData, function (index, field) {
$('<input type="hidden"/>')
.prop('name', field.name)
.val(field.value)
.appendTo(form);
});
}
if (options.fileInput && options.fileInput.length &&
options.type === 'POST') {
fileInputClones = options.fileInput.clone();
// Insert a clone for each file input field:
options.fileInput.after(function (index) {
return fileInputClones[index];
});
if (options.paramName) {
options.fileInput.each(function (index) {
$(this).prop(
'name',
paramNames[index] || options.paramName
);
});
}
// Appending the file input fields to the hidden form
// removes them from their original location:
form
.append(options.fileInput)
.prop('enctype', 'multipart/form-data')
// enctype must be set as encoding for IE:
.prop('encoding', 'multipart/form-data');
// Remove the HTML5 form attribute from the input(s):
options.fileInput.removeAttr('form');
}
form.submit();
// Insert the file input fields at their original location
// by replacing the clones with the originals:
if (fileInputClones && fileInputClones.length) {
options.fileInput.each(function (index, input) {
var clone = $(fileInputClones[index]);
// Restore the original name and form properties:
$(input)
.prop('name', clone.prop('name'))
.attr('form', clone.attr('form'));
clone.replaceWith(input);
});
}
});
form.append(iframe).appendTo(document.body);
},
abort: function () {
if (iframe) {
// javascript:false as iframe src aborts the request
// and prevents warning popups on HTTPS in IE6.
// concat is used to avoid the "Script URL" JSLint error:
iframe
.unbind('load')
.prop('src', initialIframeSrc);
}
if (form) {
form.remove();
}
}
};
}
});
// The iframe transport returns the iframe content document as response.
// The following adds converters from iframe to text, json, html, xml
// and script.
// Please note that the Content-Type for JSON responses has to be text/plain
// or text/html, if the browser doesn't include application/json in the
// Accept header, else IE will show a download dialog.
// The Content-Type for XML responses on the other hand has to be always
// application/xml or text/xml, so IE properly parses the XML response.
// See also
// https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#content-type-negotiation
$.ajaxSetup({
converters: {
'iframe text': function (iframe) {
return iframe && $(iframe[0].body).text();
},
'iframe json': function (iframe) {
return iframe && jsonAPI[jsonParse]($(iframe[0].body).text());
},
'iframe html': function (iframe) {
return iframe && $(iframe[0].body).html();
},
'iframe xml': function (iframe) {
var xmlDoc = iframe && iframe[0];
return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc :
$.parseXML((xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml) ||
$(xmlDoc.body).html());
},
'iframe script': function (iframe) {
return iframe && $.globalEval($(iframe[0].body).text());
}
}
});
}));

View file

@ -0,0 +1,752 @@
/*! jQuery UI - v1.12.1+CommonJS - 2018-02-10
* http://jqueryui.com
* Includes: widget.js
* Copyright jQuery Foundation and other contributors; Licensed MIT */
(function( factory ) {
if ( typeof define === "function" && define.amd ) {
// AMD. Register as an anonymous module.
define([ "jquery" ], factory );
} else if ( typeof exports === "object" ) {
// Node/CommonJS
factory( require( "jquery" ) );
} else {
// Browser globals
factory( jQuery );
}
}(function( $ ) {
$.ui = $.ui || {};
var version = $.ui.version = "1.12.1";
/*!
* jQuery UI Widget 1.12.1
* http://jqueryui.com
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
//>>label: Widget
//>>group: Core
//>>description: Provides a factory for creating stateful widgets with a common API.
//>>docs: http://api.jqueryui.com/jQuery.widget/
//>>demos: http://jqueryui.com/widget/
var widgetUuid = 0;
var widgetSlice = Array.prototype.slice;
$.cleanData = ( function( orig ) {
return function( elems ) {
var events, elem, i;
for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
try {
// Only trigger remove when necessary to save time
events = $._data( elem, "events" );
if ( events && events.remove ) {
$( elem ).triggerHandler( "remove" );
}
// Http://bugs.jquery.com/ticket/8235
} catch ( e ) {}
}
orig( elems );
};
} )( $.cleanData );
$.widget = function( name, base, prototype ) {
var existingConstructor, constructor, basePrototype;
// ProxiedPrototype allows the provided prototype to remain unmodified
// so that it can be used as a mixin for multiple widgets (#8876)
var proxiedPrototype = {};
var namespace = name.split( "." )[ 0 ];
name = name.split( "." )[ 1 ];
var fullName = namespace + "-" + name;
if ( !prototype ) {
prototype = base;
base = $.Widget;
}
if ( $.isArray( prototype ) ) {
prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
}
// Create selector for plugin
$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
return !!$.data( elem, fullName );
};
$[ namespace ] = $[ namespace ] || {};
existingConstructor = $[ namespace ][ name ];
constructor = $[ namespace ][ name ] = function( options, element ) {
// Allow instantiation without "new" keyword
if ( !this._createWidget ) {
return new constructor( options, element );
}
// Allow instantiation without initializing for simple inheritance
// must use "new" keyword (the code above always passes args)
if ( arguments.length ) {
this._createWidget( options, element );
}
};
// Extend with the existing constructor to carry over any static properties
$.extend( constructor, existingConstructor, {
version: prototype.version,
// Copy the object used to create the prototype in case we need to
// redefine the widget later
_proto: $.extend( {}, prototype ),
// Track widgets that inherit from this widget in case this widget is
// redefined after a widget inherits from it
_childConstructors: []
} );
basePrototype = new base();
// We need to make the options hash a property directly on the new instance
// otherwise we'll modify the options hash on the prototype that we're
// inheriting from
basePrototype.options = $.widget.extend( {}, basePrototype.options );
$.each( prototype, function( prop, value ) {
if ( !$.isFunction( value ) ) {
proxiedPrototype[ prop ] = value;
return;
}
proxiedPrototype[ prop ] = ( function() {
function _super() {
return base.prototype[ prop ].apply( this, arguments );
}
function _superApply( args ) {
return base.prototype[ prop ].apply( this, args );
}
return function() {
var __super = this._super;
var __superApply = this._superApply;
var returnValue;
this._super = _super;
this._superApply = _superApply;
returnValue = value.apply( this, arguments );
this._super = __super;
this._superApply = __superApply;
return returnValue;
};
} )();
} );
constructor.prototype = $.widget.extend( basePrototype, {
// TODO: remove support for widgetEventPrefix
// always use the name + a colon as the prefix, e.g., draggable:start
// don't prefix for widgets that aren't DOM-based
widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
}, proxiedPrototype, {
constructor: constructor,
namespace: namespace,
widgetName: name,
widgetFullName: fullName
} );
// If this widget is being redefined then we need to find all widgets that
// are inheriting from it and redefine all of them so that they inherit from
// the new version of this widget. We're essentially trying to replace one
// level in the prototype chain.
if ( existingConstructor ) {
$.each( existingConstructor._childConstructors, function( i, child ) {
var childPrototype = child.prototype;
// Redefine the child widget using the same prototype that was
// originally used, but inherit from the new version of the base
$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
child._proto );
} );
// Remove the list of existing child constructors from the old constructor
// so the old child constructors can be garbage collected
delete existingConstructor._childConstructors;
} else {
base._childConstructors.push( constructor );
}
$.widget.bridge( name, constructor );
return constructor;
};
$.widget.extend = function( target ) {
var input = widgetSlice.call( arguments, 1 );
var inputIndex = 0;
var inputLength = input.length;
var key;
var value;
for ( ; inputIndex < inputLength; inputIndex++ ) {
for ( key in input[ inputIndex ] ) {
value = input[ inputIndex ][ key ];
if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
// Clone objects
if ( $.isPlainObject( value ) ) {
target[ key ] = $.isPlainObject( target[ key ] ) ?
$.widget.extend( {}, target[ key ], value ) :
// Don't extend strings, arrays, etc. with objects
$.widget.extend( {}, value );
// Copy everything else by reference
} else {
target[ key ] = value;
}
}
}
}
return target;
};
$.widget.bridge = function( name, object ) {
var fullName = object.prototype.widgetFullName || name;
$.fn[ name ] = function( options ) {
var isMethodCall = typeof options === "string";
var args = widgetSlice.call( arguments, 1 );
var returnValue = this;
if ( isMethodCall ) {
// If this is an empty collection, we need to have the instance method
// return undefined instead of the jQuery instance
if ( !this.length && options === "instance" ) {
returnValue = undefined;
} else {
this.each( function() {
var methodValue;
var instance = $.data( this, fullName );
if ( options === "instance" ) {
returnValue = instance;
return false;
}
if ( !instance ) {
return $.error( "cannot call methods on " + name +
" prior to initialization; " +
"attempted to call method '" + options + "'" );
}
if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
return $.error( "no such method '" + options + "' for " + name +
" widget instance" );
}
methodValue = instance[ options ].apply( instance, args );
if ( methodValue !== instance && methodValue !== undefined ) {
returnValue = methodValue && methodValue.jquery ?
returnValue.pushStack( methodValue.get() ) :
methodValue;
return false;
}
} );
}
} else {
// Allow multiple hashes to be passed on init
if ( args.length ) {
options = $.widget.extend.apply( null, [ options ].concat( args ) );
}
this.each( function() {
var instance = $.data( this, fullName );
if ( instance ) {
instance.option( options || {} );
if ( instance._init ) {
instance._init();
}
} else {
$.data( this, fullName, new object( options, this ) );
}
} );
}
return returnValue;
};
};
$.Widget = function( /* options, element */ ) {};
$.Widget._childConstructors = [];
$.Widget.prototype = {
widgetName: "widget",
widgetEventPrefix: "",
defaultElement: "<div>",
options: {
classes: {},
disabled: false,
// Callbacks
create: null
},
_createWidget: function( options, element ) {
element = $( element || this.defaultElement || this )[ 0 ];
this.element = $( element );
this.uuid = widgetUuid++;
this.eventNamespace = "." + this.widgetName + this.uuid;
this.bindings = $();
this.hoverable = $();
this.focusable = $();
this.classesElementLookup = {};
if ( element !== this ) {
$.data( element, this.widgetFullName, this );
this._on( true, this.element, {
remove: function( event ) {
if ( event.target === element ) {
this.destroy();
}
}
} );
this.document = $( element.style ?
// Element within the document
element.ownerDocument :
// Element is window or document
element.document || element );
this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
}
this.options = $.widget.extend( {},
this.options,
this._getCreateOptions(),
options );
this._create();
if ( this.options.disabled ) {
this._setOptionDisabled( this.options.disabled );
}
this._trigger( "create", null, this._getCreateEventData() );
this._init();
},
_getCreateOptions: function() {
return {};
},
_getCreateEventData: $.noop,
_create: $.noop,
_init: $.noop,
destroy: function() {
var that = this;
this._destroy();
$.each( this.classesElementLookup, function( key, value ) {
that._removeClass( value, key );
} );
// We can probably remove the unbind calls in 2.0
// all event bindings should go through this._on()
this.element
.off( this.eventNamespace )
.removeData( this.widgetFullName );
this.widget()
.off( this.eventNamespace )
.removeAttr( "aria-disabled" );
// Clean up events and states
this.bindings.off( this.eventNamespace );
},
_destroy: $.noop,
widget: function() {
return this.element;
},
option: function( key, value ) {
var options = key;
var parts;
var curOption;
var i;
if ( arguments.length === 0 ) {
// Don't return a reference to the internal hash
return $.widget.extend( {}, this.options );
}
if ( typeof key === "string" ) {
// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
options = {};
parts = key.split( "." );
key = parts.shift();
if ( parts.length ) {
curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
for ( i = 0; i < parts.length - 1; i++ ) {
curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
curOption = curOption[ parts[ i ] ];
}
key = parts.pop();
if ( arguments.length === 1 ) {
return curOption[ key ] === undefined ? null : curOption[ key ];
}
curOption[ key ] = value;
} else {
if ( arguments.length === 1 ) {
return this.options[ key ] === undefined ? null : this.options[ key ];
}
options[ key ] = value;
}
}
this._setOptions( options );
return this;
},
_setOptions: function( options ) {
var key;
for ( key in options ) {
this._setOption( key, options[ key ] );
}
return this;
},
_setOption: function( key, value ) {
if ( key === "classes" ) {
this._setOptionClasses( value );
}
this.options[ key ] = value;
if ( key === "disabled" ) {
this._setOptionDisabled( value );
}
return this;
},
_setOptionClasses: function( value ) {
var classKey, elements, currentElements;
for ( classKey in value ) {
currentElements = this.classesElementLookup[ classKey ];
if ( value[ classKey ] === this.options.classes[ classKey ] ||
!currentElements ||
!currentElements.length ) {
continue;
}
// We are doing this to create a new jQuery object because the _removeClass() call
// on the next line is going to destroy the reference to the current elements being
// tracked. We need to save a copy of this collection so that we can add the new classes
// below.
elements = $( currentElements.get() );
this._removeClass( currentElements, classKey );
// We don't use _addClass() here, because that uses this.options.classes
// for generating the string of classes. We want to use the value passed in from
// _setOption(), this is the new value of the classes option which was passed to
// _setOption(). We pass this value directly to _classes().
elements.addClass( this._classes( {
element: elements,
keys: classKey,
classes: value,
add: true
} ) );
}
},
_setOptionDisabled: function( value ) {
this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
// If the widget is becoming disabled, then nothing is interactive
if ( value ) {
this._removeClass( this.hoverable, null, "ui-state-hover" );
this._removeClass( this.focusable, null, "ui-state-focus" );
}
},
enable: function() {
return this._setOptions( { disabled: false } );
},
disable: function() {
return this._setOptions( { disabled: true } );
},
_classes: function( options ) {
var full = [];
var that = this;
options = $.extend( {
element: this.element,
classes: this.options.classes || {}
}, options );
function processClassString( classes, checkOption ) {
var current, i;
for ( i = 0; i < classes.length; i++ ) {
current = that.classesElementLookup[ classes[ i ] ] || $();
if ( options.add ) {
current = $( $.unique( current.get().concat( options.element.get() ) ) );
} else {
current = $( current.not( options.element ).get() );
}
that.classesElementLookup[ classes[ i ] ] = current;
full.push( classes[ i ] );
if ( checkOption && options.classes[ classes[ i ] ] ) {
full.push( options.classes[ classes[ i ] ] );
}
}
}
this._on( options.element, {
"remove": "_untrackClassesElement"
} );
if ( options.keys ) {
processClassString( options.keys.match( /\S+/g ) || [], true );
}
if ( options.extra ) {
processClassString( options.extra.match( /\S+/g ) || [] );
}
return full.join( " " );
},
_untrackClassesElement: function( event ) {
var that = this;
$.each( that.classesElementLookup, function( key, value ) {
if ( $.inArray( event.target, value ) !== -1 ) {
that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
}
} );
},
_removeClass: function( element, keys, extra ) {
return this._toggleClass( element, keys, extra, false );
},
_addClass: function( element, keys, extra ) {
return this._toggleClass( element, keys, extra, true );
},
_toggleClass: function( element, keys, extra, add ) {
add = ( typeof add === "boolean" ) ? add : extra;
var shift = ( typeof element === "string" || element === null ),
options = {
extra: shift ? keys : extra,
keys: shift ? element : keys,
element: shift ? this.element : element,
add: add
};
options.element.toggleClass( this._classes( options ), add );
return this;
},
_on: function( suppressDisabledCheck, element, handlers ) {
var delegateElement;
var instance = this;
// No suppressDisabledCheck flag, shuffle arguments
if ( typeof suppressDisabledCheck !== "boolean" ) {
handlers = element;
element = suppressDisabledCheck;
suppressDisabledCheck = false;
}
// No element argument, shuffle and use this.element
if ( !handlers ) {
handlers = element;
element = this.element;
delegateElement = this.widget();
} else {
element = delegateElement = $( element );
this.bindings = this.bindings.add( element );
}
$.each( handlers, function( event, handler ) {
function handlerProxy() {
// Allow widgets to customize the disabled handling
// - disabled as an array instead of boolean
// - disabled class as method for disabling individual parts
if ( !suppressDisabledCheck &&
( instance.options.disabled === true ||
$( this ).hasClass( "ui-state-disabled" ) ) ) {
return;
}
return ( typeof handler === "string" ? instance[ handler ] : handler )
.apply( instance, arguments );
}
// Copy the guid so direct unbinding works
if ( typeof handler !== "string" ) {
handlerProxy.guid = handler.guid =
handler.guid || handlerProxy.guid || $.guid++;
}
var match = event.match( /^([\w:-]*)\s*(.*)$/ );
var eventName = match[ 1 ] + instance.eventNamespace;
var selector = match[ 2 ];
if ( selector ) {
delegateElement.on( eventName, selector, handlerProxy );
} else {
element.on( eventName, handlerProxy );
}
} );
},
_off: function( element, eventName ) {
eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
this.eventNamespace;
element.off( eventName ).off( eventName );
// Clear the stack to avoid memory leaks (#10056)
this.bindings = $( this.bindings.not( element ).get() );
this.focusable = $( this.focusable.not( element ).get() );
this.hoverable = $( this.hoverable.not( element ).get() );
},
_delay: function( handler, delay ) {
function handlerProxy() {
return ( typeof handler === "string" ? instance[ handler ] : handler )
.apply( instance, arguments );
}
var instance = this;
return setTimeout( handlerProxy, delay || 0 );
},
_hoverable: function( element ) {
this.hoverable = this.hoverable.add( element );
this._on( element, {
mouseenter: function( event ) {
this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
},
mouseleave: function( event ) {
this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
}
} );
},
_focusable: function( element ) {
this.focusable = this.focusable.add( element );
this._on( element, {
focusin: function( event ) {
this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
},
focusout: function( event ) {
this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
}
} );
},
_trigger: function( type, event, data ) {
var prop, orig;
var callback = this.options[ type ];
data = data || {};
event = $.Event( event );
event.type = ( type === this.widgetEventPrefix ?
type :
this.widgetEventPrefix + type ).toLowerCase();
// The original event may come from any element
// so we need to reset the target on the new event
event.target = this.element[ 0 ];
// Copy original event properties over to the new event
orig = event.originalEvent;
if ( orig ) {
for ( prop in orig ) {
if ( !( prop in event ) ) {
event[ prop ] = orig[ prop ];
}
}
}
this.element.trigger( event, data );
return !( $.isFunction( callback ) &&
callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
event.isDefaultPrevented() );
}
};
$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
if ( typeof options === "string" ) {
options = { effect: options };
}
var hasOptions;
var effectName = !options ?
method :
options === true || typeof options === "number" ?
defaultEffect :
options.effect || defaultEffect;
options = options || {};
if ( typeof options === "number" ) {
options = { duration: options };
}
hasOptions = !$.isEmptyObject( options );
options.complete = callback;
if ( options.delay ) {
element.delay( options.delay );
}
if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
element[ method ]( options );
} else if ( effectName !== method && element[ effectName ] ) {
element[ effectName ]( options.duration, options.easing, callback );
} else {
element.queue( function( next ) {
$( this )[ method ]();
if ( callback ) {
callback.call( element[ 0 ] );
}
next();
} );
}
};
} );
var widget = $.widget;
}));

1
public/medias/.gitkeep Normal file
View file

@ -0,0 +1 @@
gitkeep

1
public/uploads/.gitkeep Normal file
View file

@ -0,0 +1 @@
gitkeep

247
resources/js/media.js vendored
View file

@ -27,6 +27,7 @@ $(document).ready(function() {
var sujetId = $("#sujet_selector").val();
if(sujetId != "")
$('.dd').nestable('destroy');
$(".currentFolder").val(0);
initFolderManager(sujetId);
});
@ -265,6 +266,14 @@ $(document).ready(function() {
dossier_id: dossier_id,
libelle: libelle,
description: description,
},
success: function(result){
$(".folder_container .dd3-item[data-id='"+dossier_id+"'] > .dd3-content span").html(libelle);
$.fancybox.getInstance().close();
},
error: function(jqXHR, textStatus, errorThrown) {
$.fancybox.getInstance().close();
$.fancyMessage({title : "Attention", message : "Erreur lors de l'édition du dossier, merci d'actualiser la page.", type : "error"});
}
});
});
@ -288,15 +297,24 @@ $(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"){
$(this).attr("aria-grabbed", "false");
@ -323,16 +341,14 @@ $(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");
}
lastSelected = $(this);
}
});
// ---- Gestion des média : affichage des dossiers on draghover
@ -404,6 +420,7 @@ $(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;
@ -415,6 +432,156 @@ $(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 = $('<button/>')
.addClass('cancel')
.html('<i class="fal fa-times"></i>');
var upload_btn = $('<button/>')
.addClass('upload')
.css('display', 'none');
$('#submit').on('click',function(event){
event.preventDefault();
$("#upload_errors").html("");
$('.upload').click() //click upload buttons and upload all files in the queue
});
$('#cancel').on('click',function(event){
event.preventDefault();
$('.cancel').click() //click cancel buttons and remove all files in the queue
$("#upload_errors").html("");
});
$(".uploader-window").on("dragleave", function(){
$(this).stop().fadeOut( "fast");
});
var currentfiles = [];
$('#fileupload').fileupload({
url: "/ajax/upload-media",
dataType: 'json',
limitMultiFileUploads: 10,
maxChunkSize: 10000000,
dragover: function (e, data) {
$(".uploader-window").fadeIn( "fast");
},
add: function (e, data) {
data.files = $.map(data.files, function(file,i){
if ($.inArray(file.name,currentfiles) >= 0) {
$.fancyMessage({title : "Attention", message : "Nous ne pouvons pas envoyer plusieurs fichiers du même nom. Veuillez renommer vos fichiers puis essayez à nouveau.", type : "error"});
return null;
}
return file;
});
$.each(data.files, function (index, file) {
var uploadErrors = [];
var acceptFileTypes = /^(gif|jpe?g|png|mp4|mp3|psd|ai|eps|svg|indd|pdf)$/i;
if(file.name.split('.').pop().length && !acceptFileTypes.test(file.name.split('.').pop())) {
uploadErrors.push('Ce type de fichier n\'est pas accepté');
}
if(data.originalFiles[0]['size'].length && data.originalFiles[0]['size'] > 5000000) {
uploadErrors.push('La taille du fichier est trop grande.');
}
if(uploadErrors.length > 0) {
alert(uploadErrors.join("\n"));
return false;
}
currentfiles.push($.trim(file.name));
var row = document.createElement('div');
var col1 = document.createElement('div');
var col2 = document.createElement('div');
$(col1).append("<span>"+file.name+"</span>").append(cancel_btn.clone(true).data(data));
$(col2).append("<span>"+file.type+" - "+FileConvertSize(file.size)+"</span>");
$(col2).append(upload_btn.clone(true).data(data));
$(row).append(col1, col2);
$(".files").append(row);
$('.upload').eq(-1).on('click',function(){
data.formData = {
uid: create_UUID(),
sujet_id: $("#sujet_selector").val(),
dossier_id: $(".currentFolder").val(),
};
data.submit();
})
$('.cancel').eq(-1).on('click',function(){
$(this).parent().parent().remove();
currentfiles = arrayRemove(currentfiles, $.trim(file.name));
})
});
},
start: function (e, data) {
$('#progress').show();
},
drop: function (e, data) {
$(".uploader-window").stop().fadeOut( "fast");
},
done: function (e, data) {
$.each(data.files, function (index, file) {
currentfiles = arrayRemove(currentfiles, $.trim(file.name));
});
//---- Chargement des médias
var currentFolder = $(".currentFolder").val();
if(currentFolder == 0 || currentFolder == ""){
var count = $(".folder_container .root_folder .count");
}else{
var count = $(".folder_container .dd3-item[data-id='"+currentFolder+"'] > .dd3-content .count");
}
count.html(parseInt(count.html())+data.files.length);
},
stop: function (e,) {
$(".files").html("");
currentfiles = [];
$('#progress .progress-bar').css('width', '0%');
$('#progress').hide();
$('.upload_container').hide("fast");
var currentFolder = $(".currentFolder").val();
if(currentFolder == 0 || currentFolder == ""){
$(".root_folder").trigger("click");
}else{
$('.dd .dd-item[data-id="'+currentFolder+'"] > .dd3-content').trigger("click");
}
},
fail: function (e, data) {
$.each(data.files, function (index, file) {
$('<p style="color: red;">Erreur durant le transfert du fichier ' + file.name + '.</p>')
.appendTo('#upload_errors');
currentfiles = arrayRemove(currentfiles, $.trim(file.name));
});
},
progressall: function (e, data) {
var progress = parseInt(data.loaded / data.total * 100, 10);
$('#progress .progress-bar').css(
'width',
progress + '%'
);
}
}).prop('disabled', !$.support.fileInput)
.parent().addClass($.support.fileInput ? undefined : 'disabled');
}
});
// ---- Gestion des média : init des dossiers
@ -528,12 +695,52 @@ function loadMedia(dossier_id, sujet_id){
if(data.length == 0){
$(window).data('noMedia', true);
}
$.each(data, function (index, item) {
output += '<a class="imageItem" data-id="'+item.id+'" href="#" draggable="true" aria-grabbed="false">Mon image';
output += item.libelle;
output += '</a>';
var ico = "";
var detail = "";
var itemClass = "";
var thumb = "";
switch (item.typemedia_id) {
case 1:
case 2:
ico = '<i class="fas fa-file-image"></i>';
detail = " - "+item.largeur+"x"+item.hauteur+"px";
thumb = item.source.split('.')[0]+"_thumb."+item.extension;
break;
case 3:
ico = '<i class="fas fa-file-video"></i>';
detail = " - durée "+item.duree;
itemClass = "video";
break;
case 4:
ico = '<i class="fas fa-file-audio"></i>';
detail = " - durée "+item.duree;
itemClass = "son";
break;
case 5:
ico = '<i class="fas fa-file"></i>';
itemClass = "doc";
break;
default:
}
output += '<div class="imageItem" data-id="'+item.id+'" draggable="true" aria-grabbed="false">';
output += '<div class="contextMenu"><ul>';
output += '<li class="menu-option editItem"><i class="fas fa-edit"></i> Editer</li>';
output += '<li class="menu-option downloadItem"><i class="fas fa-file-download"></i> Télécharger</li>';
output += '<li class="menu-option addBasket"><i class="fas fa-shopping-basket"></i> Ajouter au panier</li>';
output += '<li class="menu-option deleteItem"><i class="fas fa-trash-alt"></i> Supprimer</li>';
output += '<li class="menu-option tagItem"><i class="fas fa-tags"></i> Etiquette</li>';
output += '</ul></div>';
output += '<div class="media '+itemClass+'" style="background-image:url('+thumb+')"></div>';
output += '<p class="libelle">'+item.libelle+'</p>';
output += '<div class="info">'+ico+item.extension+' - '+item.taille+detail+'</div>';
output += '</div>';
});
$('.media_container .wrapper').append(output);
if($(window).data('offset') == 0){
$(".media_container .loader").hide();
}else{
@ -586,3 +793,27 @@ function addItem(parent_id, item_id, content){
html += "<div class='dd3-content'><input type='text' value='' class='input_rename' maxlength='100' /><span>" + content + "</span><div class='count'>0</div><i class='fal fa-star'></i></div></li>";
$('.dd .dd-item[data-id="'+parent_id+'"] > ol').append(html);
}
function arrayRemove(arr, value) {
return arr.filter(function(ele){
return ele != value;
});
}
function FileConvertSize(aSize){
aSize = Math.abs(parseInt(aSize, 10));
var def = [[1, 'octets'], [1024, 'ko'], [1024*1024, 'Mo'], [1024*1024*1024, 'Go'], [1024*1024*1024*1024, 'To']];
for(var i=0; i<def.length; i++){
if(aSize<def[i][0]) return (aSize/def[i-1][0]).toFixed(2)+' '+def[i-1][1];
}
}
function create_UUID(){
var dt = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (dt + Math.random()*16)%16 | 0;
dt = Math.floor(dt/16);
return (c=='x' ? r :(r&0x3|0x8)).toString(16);
});
return uuid;
}

View file

@ -9,6 +9,7 @@
'partials/fontawesome/regular.scss',
'partials/fontawesome/light.scss',
'partials/fontawesome/brands.scss',
'partials/fileupload.scss',
'partials/common.scss',
'partials/form.scss',
'partials/media.scss',

View file

@ -283,6 +283,48 @@
}
}
/******************************************
UPLOADER
******************************************/
.uploader-window {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,86,132,.9);
z-index: 250000;
display: none;
text-align: center;
.uploader-window-content {
position: absolute;
top: 10px;
left: 10px;
right: 10px;
bottom: 10px;
border: 1px dashed #fff;
pointer-events: none;
h1{
margin: -.5em 0 0;
position: absolute;
font-weight: bold;
top: 50%;
left: 0;
right: 0;
transform: translateY(-50%);
font-size: 37px;
color: #fff;
padding: 0;
pointer-events: none;
}
}
}
/******************************************
SIDE MENU
******************************************/

172
resources/sass/partials/fileupload.scss vendored Normal file
View file

@ -0,0 +1,172 @@
/*
* 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%;
transform: translate(-50%, -50%);
width: 300px;
height: 400px;
background-color: $white;
z-index: 100;
border-radius: 10px;
.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;
user-select: none;
background-image: none;
border: 1px solid transparent;
border-radius: 4px;
width: 100%;
font-size: 15px;
color: $grey;
padding: 16px;
cursor: pointer;
border-bottom: 1px solid $grey2;
i{
color : $lightblue;
font-size: 18px;
margin-right: 10px;
}
input {
position: absolute;
top: 0;
right: 0;
margin: 0;
opacity: 0;
font-size: 200px !important;
direction: ltr;
cursor: pointer;
}
}
/* Fixes for IE < 8 */
@media screen\9 {
.fileinput-button input {
filter: alpha(opacity=0);
font-size: 100%;
height: 100%;
}
}
.progress {
display: none;
height: 6px;
overflow: hidden;
background-color: #f5f5f5;
position: absolute;
top: 0px;
left: 0;
z-index: 999999999999;
width: 100%;
.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,.15);
transition: width .6s ease;
&.progress-bar-success {
background-color: #5cb85c;
}
}
}
.content_wrapper{
height: 286px;
overflow-y: auto;
}
#files{
>div{
width: 100%;
padding: 10px;
border-bottom: 1px solid #e8ebed;
div:first-child{
color: $black;
margin-bottom: 5px;
font-size: 14px;
position: relative;
span{
white-space: nowrap;
display: block;
text-overflow: ellipsis;
overflow: hidden;
max-width: 91%;
}
}
div:last-child{
color: $grey;
}
button{
display: none;
border: none;
background-color: transparent;
position: absolute;
right: 0;
top: -3px;
cursor: pointer;
i{
color: #337ab7;
font-size: 19px;
}
}
&:hover{
button{
display: block;
}
}
}
}
.upload_bar{
border-top: 1px solid $grey2;
width: 100%;
height: 60px;
position: absolute;
bottom: 0;
padding: 13px 10px;
#submit{
display: inline-block;
}
#cancel , #close_upload_form{
color: $grey;
cursor: pointer;
margin-left: 15px;
}
}
}

View file

@ -115,12 +115,6 @@ h1{
display: inline-block;
}
.group:after {
content: "";
display: table;
clear: both;
}
.filter_row{
margin-bottom: 10px;
.right_col{

View file

@ -13,11 +13,62 @@
.search_wrapper{
padding: 30px 5px 10px 40px;
min-height: 129px;
.search_filters{
display: inline-flex;
align-items: center;
padding: 0px 10px;
>div{
display: flex;
align-items: center;
margin-right: 10px;
i{
margin-left: 10px;
}
}
}
}
.action_wrapper{
background-color: $grey;
width: 100%;
min-height: 45px;
a{
font-size: 14px;
padding: 15px 20px;
display: inline-block;
border-right: 1px solid #505050;
float: left;
transition: 0.3s ease-in-out;
&:hover{
background-color: $grey3;
}
i{
background-color: $black;
border-radius: 20px;
margin-right: 5px;
padding: 5px 6px;
font-size: 11px;
color: $white;
}
&.action_download_media i{
background-color: $orange;
}
&.action_add_basket i{
background-color: $teal;
}
&.action_delete_media i{
background-color: $red;
}
&.action_tag_media i{
background-color: $cyan;
}
}
}
}
@ -61,20 +112,147 @@
justify-content: center;
top: 0;
}
.wrapper{
display: flex;
flex-wrap: wrap;
.imageItem{
padding: 51px 20px;
margin: 30px 10px;
display: inline-block;
border: 1px solid grey;
.imageItem{
display: inline-block;
border: 1px solid grey;
width: 202px;
margin: 8px 10px;
background-color: $grey3;
transition: 0.3s ease-in-out;
position: relative;
padding-bottom: 25px;
cursor: pointer;
&[aria-grabbed="true"] {
background: #8ad;
color: #fff;
}
&:focus {
outline: none;
box-shadow: 0 0 0 2px #68b, inset 0 0 0 1px #ddd;
.contextMenu{
position: absolute;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.7);
left: 0px;
top: 0px;
z-index: 2;
display: none;
transform: rotateY(180deg);
color: $white;
justify-content: center;
align-items: center;
.menu-option{
padding: 10px;
transition: 0.3s ease-in-out;
i{
margin-right: 5px;
}
&:hover{
background-color: #2ea8e5;
}
}
}
&.flip{
transform: rotateY(180deg);
.contextMenu{
display: flex;
}
}
.media{
height: 200px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
position: relative;
&::before {
transform: translate(-50%,-50%);
display: block;
position: absolute;
left: 50%;
top: 50%;
text-align: center;
text-indent: 0;
color: $white;
font-size: 59px;
z-index: 1;
}
&.video{
&::before {
content: "\f167";
font-family: "Font Awesome 5 Brands";
}
}
&.son{
&::before {
content: "\f58f";
font-family: "Font Awesome 5 Pro";
font-weight: 900;
}
}
&.doc{
&::before {
content: "\f15c";
font-family: "Font Awesome 5 Pro";
font-weight: 900;
}
}
}
.libelle{
padding: 4px;
text-align: center;
color: $white;
margin: 0;
word-wrap: break-word;
}
.info{
position: absolute;
bottom: 0;
padding: 4px;
font-size: 11px;
i{
margin-right: 7px;
}
}
&[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: $lightblue;
font-size: 25px;
z-index: 2;
}
&::after {
content: "";
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.5);
position: absolute;
left: 0px;
top: 0px;
z-index: 1;
}
}
&:hover{
background-color: $grey;
}
}
}
}
@ -90,6 +268,7 @@
width: 340px;
height: 100%;
transition: 0.3s ease-in-out;
z-index: 1;
&.collapse{
transform: translateX(-100%);

View file

@ -61,3 +61,15 @@ table {
*, *:before, *:after {
box-sizing: inherit;
}
.group:before,
.group:after {
content: "";
display: table;
}
.group:after {
clear: both;
}
.group {
zoom: 1; /* For IE 6/7 (trigger hasLayout) */
}

View file

@ -38,6 +38,13 @@
</p>
</div>
<div class="uploader-window">
<div class="uploader-window-content">
<h1>Déposez vos fichiers pour les téléverser</h1>
</div>
</div>
<!-- Scripts -->
<script src="{{ asset('js/jquery.fancybox.min.js') }}" defer></script>
<script src="{{ asset('js/app.js') }}"></script>

View file

@ -39,9 +39,24 @@
<div class="search_wrapper">
<input type="text" value="" placeholder="rechercher un média...">
<a href="#" class="btn btn-square btn-black">Rechercher</a>
<div class="search_filters group">
<div class="filters_type_media">Type de média <i class="fas fa-caret-down"></i></div>
<div class="filters_type_vue">Type de vue <i class="fas fa-caret-down"></i></div>
<div class="filters_etiquette">Etiquette <i class="fas fa-caret-down"></i></div>
<div class="filters_arcadia">
<input type="checkbox" id="arcadia" name="arcadia" >
<label for="arcadia">Lié au référentiel</label> </div>
</div>
<div class="search_filters_list">
</div>
</div>
<div class="action_wrapper">
<a href="#" class="action_add_media"><i class="fas fa-file-upload"></i> Ajouter</a>
<div class="action_wrapper group">
<a href="#" class="action_add_media"><i class="fas fa-file-upload"></i> Ajouter un média</a>
<a href="#" class="action_download_media"><i class="fas fa-file-download"></i> Télécharger</a>
<a href="#" class="action_add_basket"><i class="fas fa-shopping-basket"></i> Ajouter au panier</a>
<a href="#" class="action_delete_media"><i class="fas fa-trash-alt"></i> Supprimer</a>
<a href="#" class="action_tag_media"><i class="fas fa-tags"></i> Etiquette</a>
</div>
</header>
<div style="display:none;" class="scrollLoader"><div class="animated slideInUp"><i class="fal fa-circle-notch fa-spin"></i> Chargements des médias</div></div>
@ -62,7 +77,33 @@
<a href="#" class="btn form_folder_save btn-square"><i class="fal fa-spinner-third fa-spin"></i><i class="fas fa-share"></i> Enregistrer</a><a href="#" class="btn close_popup btn-black btn-square">Fermer</a>
</p>
</div>
<div class="upload_container">
<span class="fileinput-button">
<i class="fas fa-plus-circle"></i><span> Ajouter vos médias</span>
<input id="fileupload" type="file" name="files[]" multiple>
</span>
<div class="content_wrapper">
<!-- The container for the uploaded errors -->
<div id="upload_errors"></div>
<!-- The container for the uploaded files -->
<div id="files" class="files"></div>
</div>
<div class="upload_bar">
<a id="submit" class="btn" href="#">Transférer</a>
<a id="close_upload_form" class="" href="#">Fermer</a>
<!-- The global progress bar -->
<div id="progress" class="progress">
<div class="progress-bar progress-bar-success"></div>
</div>
</div>
<br>
</div>
@endsection
@section('scripts')
<script src="{{ asset('js/jquery.nestable.min.js') }}" defer></script>
<script src="{{ asset('js/uploadfile/vendor/jquery.ui.widget.js') }}"></script>
<script src="{{ asset('js/uploadfile/jquery.iframe-transport.js') }}"></script>
<script src="{{ asset('js/uploadfile/jquery.fileupload.js') }}"></script>
@endsection

View file

@ -0,0 +1,31 @@
@extends('layouts.app')
@include('layouts.header')
@section('content')
<div class="upload_container">
<span class="btn btn-success fileinput-button">
<span><i class="fal fa-plus-circle"></i> Ajouter des médias</span>
<input id="fileupload" type="file" name="files[]" multiple>
</span>
<a id="submit" class="btn" href="#">Télécharger</a>
<a id="cancel" class="btn" href="#">Supprimer</a>
<br>
<br>
<!-- The global progress bar -->
<div id="progress" class="progress">
<div class="progress-bar progress-bar-success"></div>
</div>
<!-- The container for the uploaded errors -->
<div id="upload_errors"></div>
<!-- The container for the uploaded files -->
<div id="files" class="files"></div>
<br>
</div>
@endsection
@section('scripts')
<script src="{{ asset('js/uploadfile/vendor/jquery.ui.widget.js') }}"></script>
<script src="{{ asset('js/uploadfile/jquery.iframe-transport.js') }}"></script>
<script src="{{ asset('js/uploadfile/jquery.fileupload.js') }}"></script>
@endsection

View file

@ -27,6 +27,9 @@ Route::group(['middleware' => ['auth']], function(){
Route::post('/ajax/load-media', 'MediaController@loadMedia');
Route::post('/ajax/move-media', 'MediaController@moveMedia');
Route::get('/upload', 'UploadController@index');
Route::post('/ajax/upload-media', 'UploadController@storeMedia');
Route::resource('user', 'UserController');
Route::post('/check-matricule', 'UserController@checkMatricule');
Route::resource('dossier', 'DossierController');