From: Vincent Vanwaelscappel Date: Mon, 19 Apr 2021 07:23:20 +0000 (+0200) Subject: wip #4406 @8 X-Git-Url: http://git.cubedesigners.com/?a=commitdiff_plain;h=f914a92df7f0ad3be5b3b9811b89cc1e355673c2;p=grandvision-ranking.git wip #4406 @8 --- diff --git a/.gitignore b/.gitignore index 0ae59f0..17e6805 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ Homestead.json Homestead.yaml npm-debug.log yarn-error.log +yarn.lock +/resources/css/app.css +/resources/css/app.css.map diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index e78f884..615dfe1 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -2,16 +2,32 @@ namespace App\Http\Controllers; +use App\Models\FeedbackProcess; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Routing\Controller as BaseController; +use Symfony\Component\HttpFoundation\FileBag; class Controller extends BaseController { use AuthorizesRequests, DispatchesJobs, ValidatesRequests; - public function process(){ - dd($_POST,$_FILES); + public function process() + { + $process = new FeedbackProcess(request()->get('_session')); + $process->process(); + + } + + public function upload() + { + /** @var FileBag $files */ + $files = request()->files; + + $process = new FeedbackProcess(request()->get('_session')); + foreach ($files as $name => $file) { + $process->addFile($name, $file); + } } } diff --git a/app/Models/FeedbackProcess.php b/app/Models/FeedbackProcess.php new file mode 100644 index 0000000..7b88d32 --- /dev/null +++ b/app/Models/FeedbackProcess.php @@ -0,0 +1,128 @@ +setPath($path); + if (!file_exists($path)) { + if (!mkdir($path, 0777, true) && !is_dir($path)) { + throw new \RuntimeException(sprintf('Directory "%s" was not created', $path)); + } + } else { + $this->loadSession(); + } + } + + public function loadSession() + { + $jsonFile = $this->_getSessionFile(); + if (file_exists($jsonFile)) { + $json = json_decode(file_get_contents($jsonFile), true); + $this->setTemplate($json['template']); + $this->setFeedbacks($json['feedbacks']); + } + + } + + protected function _getSessionFile() + { + return $this->getPath() . '/session.json'; + } + + /** + * @param $name + * @param $uploadedFile UploadedFile + */ + public function addFile($name, $uploadedFile) + { + $target = $uploadedFile->move($this->getPath()); + + if ($name === 'template') { + $this->setTemplate($target->getPathname()); + } else if ($name === 'feedbacks') { + $this->addFeedback($target->getPathname()); + } + } + + /** + * @param mixed $path + */ + public function setPath($path): void + { + $this->_path = $path; + } + + /** + * @return mixed + */ + public function getPath() + { + return $this->_path; + } + + /** + * @return mixed + */ + public function getTemplate() + { + return $this->_template; + } + + /** + * @param mixed $template + */ + public function setTemplate($template): void + { + $this->_template = $template; + } + + /** + * @return array + */ + public function getFeedbacks(): array + { + return $this->_feedbacks; + } + + /** + * @param array $feedbacks + */ + public function setFeedbacks(array $feedbacks): void + { + $this->_feedbacks = $feedbacks; + } + + public function addFeedback($feedback): void + { + $this->_feedbacks[] = $feedback; + } + + public function __destruct() + { + $this->saveSession(); + } + + /** + * @throws \JsonException + */ + public function saveSession() + { + file_put_contents($this->_getSessionFile(), json_encode(['template' => $this->getTemplate(), 'feedbacks' => $this->getFeedbacks()], JSON_THROW_ON_ERROR)); + } + + public function process() + { + dd($this); + } +} diff --git a/composer.json b/composer.json index b5cbe09..c9a7482 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,8 @@ "guzzlehttp/guzzle": "^7.0.1", "laravel/framework": "^8.12", "laravel/tinker": "^2.5", - "phpoffice/phpspreadsheet": "^1.17" + "phpoffice/phpspreadsheet": "^1.17", + "ext-json": "*" }, "require-dev": { "facade/ignition": "^2.5", diff --git a/public/images/logoGV.png b/public/images/logoGV.png new file mode 100644 index 0000000..1775e9d Binary files /dev/null and b/public/images/logoGV.png differ diff --git a/resources/css/app.less b/resources/css/app.less index 96ff524..7d046da 100644 --- a/resources/css/app.less +++ b/resources/css/app.less @@ -1,4 +1,66 @@ +@blue: #0057b8; +@orange: #e35205; +@grey: #aaa; + body { - background-color: #fff; + color: @blue; + background-color: #eee; + font-weight: 300; + font-family: Roboto; +} + +main { + text-align: center; + max-width: 900px; + padding: 0 50px; + margin: 0 auto; +} + +.logo { + display: inline-block; + width: 300px; + margin: 50px 0; +} + +h1 { + margin-top: 20px; + text-transform: uppercase; + font-weight: 300; +} + +form { + color: #000; + text-align: left; + + .dropzone { + border-radius: 10px; + color: @grey; + border: 2px dashed @blue; + } + + label { + display: block; + margin-top: 30px; + + span { + display: block; + margin: 5px 0; + } + } + + input[type="submit"] { + display: block; + font-size: 20px; + padding: 12px 30px; + color: #fff; + background-color: @orange; + border-radius: 5px; + cursor: pointer; + margin: 50px auto; + width: 200px; + font-weight: 300; + font-family: Roboto; + } } +@import "dropzone.css"; diff --git a/resources/css/dropzone.css b/resources/css/dropzone.css new file mode 100644 index 0000000..b0cf0fe --- /dev/null +++ b/resources/css/dropzone.css @@ -0,0 +1,468 @@ +@-webkit-keyframes passing-through { + 0% { + opacity: 0; + -webkit-transform: translateY(40px); + -moz-transform: translateY(40px); + -ms-transform: translateY(40px); + -o-transform: translateY(40px); + transform: translateY(40px); + } + 30%, 70% { + opacity: 1; + -webkit-transform: translateY(0px); + -moz-transform: translateY(0px); + -ms-transform: translateY(0px); + -o-transform: translateY(0px); + transform: translateY(0px); + } + 100% { + opacity: 0; + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + transform: translateY(-40px); + } +} +@-moz-keyframes passing-through { + 0% { + opacity: 0; + -webkit-transform: translateY(40px); + -moz-transform: translateY(40px); + -ms-transform: translateY(40px); + -o-transform: translateY(40px); + transform: translateY(40px); + } + 30%, 70% { + opacity: 1; + -webkit-transform: translateY(0px); + -moz-transform: translateY(0px); + -ms-transform: translateY(0px); + -o-transform: translateY(0px); + transform: translateY(0px); + } + 100% { + opacity: 0; + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + transform: translateY(-40px); + } +} +@keyframes passing-through { + 0% { + opacity: 0; + -webkit-transform: translateY(40px); + -moz-transform: translateY(40px); + -ms-transform: translateY(40px); + -o-transform: translateY(40px); + transform: translateY(40px); + } + 30%, 70% { + opacity: 1; + -webkit-transform: translateY(0px); + -moz-transform: translateY(0px); + -ms-transform: translateY(0px); + -o-transform: translateY(0px); + transform: translateY(0px); + } + 100% { + opacity: 0; + -webkit-transform: translateY(-40px); + -moz-transform: translateY(-40px); + -ms-transform: translateY(-40px); + -o-transform: translateY(-40px); + transform: translateY(-40px); + } +} +@-webkit-keyframes slide-in { + 0% { + opacity: 0; + -webkit-transform: translateY(40px); + -moz-transform: translateY(40px); + -ms-transform: translateY(40px); + -o-transform: translateY(40px); + transform: translateY(40px); + } + 30% { + opacity: 1; + -webkit-transform: translateY(0px); + -moz-transform: translateY(0px); + -ms-transform: translateY(0px); + -o-transform: translateY(0px); + transform: translateY(0px); + } +} +@-moz-keyframes slide-in { + 0% { + opacity: 0; + -webkit-transform: translateY(40px); + -moz-transform: translateY(40px); + -ms-transform: translateY(40px); + -o-transform: translateY(40px); + transform: translateY(40px); + } + 30% { + opacity: 1; + -webkit-transform: translateY(0px); + -moz-transform: translateY(0px); + -ms-transform: translateY(0px); + -o-transform: translateY(0px); + transform: translateY(0px); + } +} +@keyframes slide-in { + 0% { + opacity: 0; + -webkit-transform: translateY(40px); + -moz-transform: translateY(40px); + -ms-transform: translateY(40px); + -o-transform: translateY(40px); + transform: translateY(40px); + } + 30% { + opacity: 1; + -webkit-transform: translateY(0px); + -moz-transform: translateY(0px); + -ms-transform: translateY(0px); + -o-transform: translateY(0px); + transform: translateY(0px); + } +} +@-webkit-keyframes pulse { + 0% { + -webkit-transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } + 10% { + -webkit-transform: scale(1.1); + -moz-transform: scale(1.1); + -ms-transform: scale(1.1); + -o-transform: scale(1.1); + transform: scale(1.1); + } + 20% { + -webkit-transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } +} +@-moz-keyframes pulse { + 0% { + -webkit-transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } + 10% { + -webkit-transform: scale(1.1); + -moz-transform: scale(1.1); + -ms-transform: scale(1.1); + -o-transform: scale(1.1); + transform: scale(1.1); + } + 20% { + -webkit-transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } +} +@keyframes pulse { + 0% { + -webkit-transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } + 10% { + -webkit-transform: scale(1.1); + -moz-transform: scale(1.1); + -ms-transform: scale(1.1); + -o-transform: scale(1.1); + transform: scale(1.1); + } + 20% { + -webkit-transform: scale(1); + -moz-transform: scale(1); + -ms-transform: scale(1); + -o-transform: scale(1); + transform: scale(1); + } +} +.dropzone, .dropzone * { + box-sizing: border-box; +} + +.dropzone { + min-height: 150px; + border: 2px solid rgba(0, 0, 0, 0.3); + background: white; + padding: 20px 20px; +} +.dropzone.dz-clickable { + cursor: pointer; +} +.dropzone.dz-clickable * { + cursor: default; +} +.dropzone.dz-clickable .dz-message, .dropzone.dz-clickable .dz-message * { + cursor: pointer; +} +.dropzone.dz-started .dz-message { + display: none; +} +.dropzone.dz-drag-hover { + border-style: solid; +} +.dropzone.dz-drag-hover .dz-message { + opacity: 0.5; +} +.dropzone .dz-message { + text-align: center; + margin: 2em 0; +} +.dropzone .dz-message .dz-button { + background: none; + color: inherit; + border: none; + padding: 0; + font: inherit; + cursor: pointer; + outline: inherit; +} +.dropzone .dz-preview { + position: relative; + display: inline-block; + vertical-align: top; + margin: 16px; + min-height: 100px; +} +.dropzone .dz-preview:hover { + z-index: 1000; +} +.dropzone .dz-preview:hover .dz-details { + opacity: 1; +} +.dropzone .dz-preview.dz-file-preview .dz-image { + border-radius: 20px; + background: #999; + background: linear-gradient(to bottom, #eee, #ddd); +} +.dropzone .dz-preview.dz-file-preview .dz-details { + opacity: 1; +} +.dropzone .dz-preview.dz-image-preview { + background: white; +} +.dropzone .dz-preview.dz-image-preview .dz-details { + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + -ms-transition: opacity 0.2s linear; + -o-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; +} +.dropzone .dz-preview .dz-remove { + font-size: 14px; + text-align: center; + display: block; + cursor: pointer; + border: none; +} +.dropzone .dz-preview .dz-remove:hover { + text-decoration: underline; +} +.dropzone .dz-preview:hover .dz-details { + opacity: 1; +} +.dropzone .dz-preview .dz-details { + z-index: 20; + position: absolute; + top: 0; + left: 0; + opacity: 0; + font-size: 13px; + min-width: 100%; + max-width: 100%; + padding: 2em 1em; + text-align: center; + color: rgba(0, 0, 0, 0.9); + line-height: 150%; +} +.dropzone .dz-preview .dz-details .dz-size { + margin-bottom: 1em; + font-size: 16px; +} +.dropzone .dz-preview .dz-details .dz-filename { + white-space: nowrap; +} +.dropzone .dz-preview .dz-details .dz-filename:hover span { + border: 1px solid rgba(200, 200, 200, 0.8); + background-color: rgba(255, 255, 255, 0.8); +} +.dropzone .dz-preview .dz-details .dz-filename:not(:hover) { + overflow: hidden; + text-overflow: ellipsis; +} +.dropzone .dz-preview .dz-details .dz-filename:not(:hover) span { + border: 1px solid transparent; +} +.dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span { + background-color: rgba(255, 255, 255, 0.4); + padding: 0 0.4em; + border-radius: 3px; +} +.dropzone .dz-preview:hover .dz-image img { + -webkit-transform: scale(1.05, 1.05); + -moz-transform: scale(1.05, 1.05); + -ms-transform: scale(1.05, 1.05); + -o-transform: scale(1.05, 1.05); + transform: scale(1.05, 1.05); + -webkit-filter: blur(8px); + filter: blur(8px); +} +.dropzone .dz-preview .dz-image { + border-radius: 20px; + overflow: hidden; + width: 120px; + height: 120px; + position: relative; + display: block; + z-index: 10; +} +.dropzone .dz-preview .dz-image img { + display: block; +} +.dropzone .dz-preview.dz-success .dz-success-mark { + -webkit-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); + -moz-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); + -ms-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); + -o-animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); + animation: passing-through 3s cubic-bezier(0.77, 0, 0.175, 1); +} +.dropzone .dz-preview.dz-error .dz-error-mark { + opacity: 1; + -webkit-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); + -moz-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); + -ms-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); + -o-animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); + animation: slide-in 3s cubic-bezier(0.77, 0, 0.175, 1); +} +.dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark { + pointer-events: none; + opacity: 0; + z-index: 500; + position: absolute; + display: block; + top: 50%; + left: 50%; + margin-left: -27px; + margin-top: -27px; +} +.dropzone .dz-preview .dz-success-mark svg, .dropzone .dz-preview .dz-error-mark svg { + display: block; + width: 54px; + height: 54px; +} +.dropzone .dz-preview.dz-processing .dz-progress { + opacity: 1; + -webkit-transition: all 0.2s linear; + -moz-transition: all 0.2s linear; + -ms-transition: all 0.2s linear; + -o-transition: all 0.2s linear; + transition: all 0.2s linear; +} +.dropzone .dz-preview.dz-complete .dz-progress { + opacity: 0; + -webkit-transition: opacity 0.4s ease-in; + -moz-transition: opacity 0.4s ease-in; + -ms-transition: opacity 0.4s ease-in; + -o-transition: opacity 0.4s ease-in; + transition: opacity 0.4s ease-in; +} +.dropzone .dz-preview:not(.dz-processing) .dz-progress { + -webkit-animation: pulse 6s ease infinite; + -moz-animation: pulse 6s ease infinite; + -ms-animation: pulse 6s ease infinite; + -o-animation: pulse 6s ease infinite; + animation: pulse 6s ease infinite; +} +.dropzone .dz-preview .dz-progress { + opacity: 1; + z-index: 1000; + pointer-events: none; + position: absolute; + height: 16px; + left: 50%; + top: 50%; + margin-top: -8px; + width: 80px; + margin-left: -40px; + background: rgba(255, 255, 255, 0.9); + -webkit-transform: scale(1); + border-radius: 8px; + overflow: hidden; +} +.dropzone .dz-preview .dz-progress .dz-upload { + background: #333; + background: linear-gradient(to bottom, #666, #444); + position: absolute; + top: 0; + left: 0; + bottom: 0; + width: 0; + -webkit-transition: width 300ms ease-in-out; + -moz-transition: width 300ms ease-in-out; + -ms-transition: width 300ms ease-in-out; + -o-transition: width 300ms ease-in-out; + transition: width 300ms ease-in-out; +} +.dropzone .dz-preview.dz-error .dz-error-message { + display: block; +} +.dropzone .dz-preview.dz-error:hover .dz-error-message { + opacity: 1; + pointer-events: auto; +} +.dropzone .dz-preview .dz-error-message { + pointer-events: none; + z-index: 1000; + position: absolute; + display: block; + display: none; + opacity: 0; + -webkit-transition: opacity 0.3s ease; + -moz-transition: opacity 0.3s ease; + -ms-transition: opacity 0.3s ease; + -o-transition: opacity 0.3s ease; + transition: opacity 0.3s ease; + border-radius: 8px; + font-size: 13px; + top: 130px; + left: -10px; + width: 140px; + background: #be2626; + background: linear-gradient(to bottom, #be2626, #a92222); + padding: 0.5em 1.2em; + color: white; +} +.dropzone .dz-preview .dz-error-message:after { + content: ""; + position: absolute; + top: -6px; + left: 64px; + width: 0; + height: 0; + border-left: 6px solid transparent; + border-right: 6px solid transparent; + border-bottom: 6px solid #be2626; +} \ No newline at end of file diff --git a/resources/js/app.js b/resources/js/app.js index fe42b63..3935e70 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -3,35 +3,54 @@ var $ = require("jquery"); import Dropzone from "dropzone"; +// Dropzone.prototype.defaultOptions.dictDefaultMessage = "Drop files here to upload"; +// Dropzone.prototype.defaultOptions.dictFallbackMessage = "Your browser does not support drag'n'drop file uploads."; +// Dropzone.prototype.defaultOptions.dictFallbackText = "Please use the fallback form below to upload your files like in the olden days."; +// Dropzone.prototype.defaultOptions.dictFileTooBig = "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB."; +// Dropzone.prototype.defaultOptions.dictInvalidFileType = "You can't upload files of this type."; +// Dropzone.prototype.defaultOptions.dictResponseError = "Server responded with {{statusCode}} code."; +// Dropzone.prototype.defaultOptions.dictCancelUpload = "Cancel upload"; +// Dropzone.prototype.defaultOptions.dictCancelUploadConfirmation = "Are you sure you want to cancel this upload?"; +// Dropzone.prototype.defaultOptions.dictRemoveFile = "Remove file"; +// Dropzone.prototype.defaultOptions.dictMaxFilesExceeded = "You can not upload any more files."; + var dropzones = []; let dropzone1 = $('#template').get(0); let dropzone2 = $('#feedbacks').get(0); +var message = 'Cliquer ou glisser un fichier pour charger'; +var removeFile = 'Retirer ce fichier'; +var token = $('input[name="_token"]').attr('value'); +var session = $('input[name="_session"]').attr('value'); + var myDropzone = new Dropzone(dropzone1, { - url: window.location.pathname, - autoProcessQueue: false, + dictDefaultMessage: message, + dictRemoveFile: removeFile, + url: '/upload', + autoProcessQueue: true, autoDiscover: false, uploadMultiple: false, parallelUploads: 1, maxFiles: 1, paramName: 'template', - addRemoveLinks: true, - chunking: true, - retryChunks: true, - parallelChunkUploads: true, + sending: function (file, xhr, formData) { + formData.append("_token", token); + formData.append("_session", session); + }, }); dropzones.push(myDropzone) myDropzone = new Dropzone(dropzone2, { - url: window.location.pathname, - autoProcessQueue: false, + dictDefaultMessage: message, + url: '/upload', + autoProcessQueue: true, autoDiscover: false, uploadMultiple: false, parallelUploads: 1, maxFiles: 30, paramName: 'feedbacks', - addRemoveLinks: true, - chunking: true, - retryChunks: true, - parallelChunkUploads: true, + sending: function (file, xhr, formData) { + formData.append("_token", token); + formData.append("_session", session); + }, }); dropzones.push(myDropzone) diff --git a/resources/views/welcome.blade.php b/resources/views/welcome.blade.php index 9a6f62f..95f5f1c 100644 --- a/resources/views/welcome.blade.php +++ b/resources/views/welcome.blade.php @@ -7,7 +7,7 @@ GrandVision Ranking App - +