Implemented file uploading
This commit is contained in:
parent
78ad303236
commit
44c08b76f9
File diff suppressed because it is too large
Load Diff
|
|
@ -33,4 +33,6 @@
|
|||
@import "controls/panels.less";
|
||||
@import "controls/selector-group.less";
|
||||
@import "controls/tree-path.less";
|
||||
@import "controls/namevaluelist.less";
|
||||
@import "controls/namevaluelist.less";
|
||||
@import "controls/progressbar.less";
|
||||
@import "controls/alert.less";
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
.sweet-alert {
|
||||
text-align: left;
|
||||
|
||||
h4 {
|
||||
margin: 10px 0 20px 0;
|
||||
color: #2b3e50;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
p.text-muted {
|
||||
margin-bottom: 20px;
|
||||
color: #555555;
|
||||
}
|
||||
}
|
||||
|
|
@ -257,6 +257,7 @@ table.table.data {
|
|||
&.clickable {
|
||||
cursor: pointer;
|
||||
.user-select(none);
|
||||
}
|
||||
|
||||
td.column-compact {
|
||||
padding: 0;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
div.panel {
|
||||
@panel-border-color: #ecf0f1;
|
||||
@panel-border-color: #e8eaeb;
|
||||
|
||||
padding: 20px;
|
||||
|
||||
|
|
@ -47,7 +47,7 @@ div.panel {
|
|||
}
|
||||
|
||||
&:before {
|
||||
.triangle(down, 17px, 9px, #edeeef);
|
||||
.triangle(down, 17px, 9px, #e8eaeb);
|
||||
position: absolute;
|
||||
left: 14px;
|
||||
bottom: -9px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
div.progress {
|
||||
height: 9px;
|
||||
.box-shadow(none);
|
||||
background: #d9dee0;
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
line-height: 9px;
|
||||
.box-shadow(none);
|
||||
background-color: #2f99da;
|
||||
|
||||
&.progress-bar-success {
|
||||
background-color: #31ac5f;
|
||||
}
|
||||
}
|
||||
|
|
@ -131,6 +131,19 @@ class MediaLibrary
|
|||
return $this->getStorageDisk()->get($fullPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts a file to the library.
|
||||
* @param string $path Specifies the file path relative the the Library root.
|
||||
* @param string $contents Specifies the file contents.
|
||||
* @return boolean
|
||||
*/
|
||||
public function put($path, $contents)
|
||||
{
|
||||
$path = self::validatePath($path);
|
||||
$fullPath = $this->getMediaPath($path);
|
||||
return $this->getStorageDisk()->put($fullPath, $contents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the Library cache.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<?= Block::put('head') ?><?= Block::endPut() ?>
|
||||
|
||||
<?= Block::put('body') ?>
|
||||
<div class="layout">
|
||||
<?= Form::open(['class'=>'layout']) ?>
|
||||
<?= $this->widget->manager->render() ?>
|
||||
</div>
|
||||
<?= Form::close() ?>
|
||||
<?= Block::endPut() ?>
|
||||
|
|
@ -204,6 +204,8 @@ return [
|
|||
'return_to_parent' => 'Return to the parent folder',
|
||||
'return_to_parent_label' => 'Go up ..',
|
||||
'nothing_selected' => 'Nothing is selected.',
|
||||
'multiple_selected' => 'Multiple items selected.'
|
||||
'multiple_selected' => 'Multiple items selected.',
|
||||
'uploading_file_num' => 'Uploading :number file(s)...',
|
||||
'uploading_complete' => 'Upload complete'
|
||||
]
|
||||
];
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ class MediaManager extends WidgetBase
|
|||
|
||||
parent::__construct($controller, []);
|
||||
$this->bindToController();
|
||||
|
||||
$this->handleUploads();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -49,9 +51,9 @@ class MediaManager extends WidgetBase
|
|||
return $this->makePartial('body');
|
||||
}
|
||||
|
||||
/*
|
||||
* Event handlers
|
||||
*/
|
||||
//
|
||||
// Event handlers
|
||||
//
|
||||
|
||||
public function onSearch()
|
||||
{
|
||||
|
|
@ -140,9 +142,9 @@ class MediaManager extends WidgetBase
|
|||
];
|
||||
}
|
||||
|
||||
/*
|
||||
* Methods for th internal use
|
||||
*/
|
||||
//
|
||||
// Methods for th internal use
|
||||
//
|
||||
|
||||
protected function prepareVars()
|
||||
{
|
||||
|
|
@ -441,4 +443,37 @@ class MediaManager extends WidgetBase
|
|||
return $originalDimensions;
|
||||
}
|
||||
}
|
||||
|
||||
protected function handleUploads()
|
||||
{
|
||||
$fileName = null;
|
||||
|
||||
try {
|
||||
$uploadedFile = Input::file('file_data');
|
||||
|
||||
if (!is_object($uploadedFile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fileName = $uploadedFile->getClientOriginalName();
|
||||
|
||||
// See mime type handling in the asset manager
|
||||
|
||||
if (!$uploadedFile->isValid())
|
||||
throw new ApplicationException($uploadedFile->getErrorMessage());
|
||||
|
||||
$path = Input::get('path');
|
||||
$path = MediaLibrary::validatePath($path);
|
||||
|
||||
MediaLibrary::instance()->put($path.'/'.$fileName,
|
||||
File::get($uploadedFile->getRealPath()));
|
||||
|
||||
die('success');
|
||||
}
|
||||
catch (Exception $ex) {
|
||||
Response::make($ex->getMessage(), 406)->send();
|
||||
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -256,12 +256,54 @@ div[data-control="media-manager"] .list-container {
|
|||
}
|
||||
div[data-control="media-manager"] [data-control="item-list"] {
|
||||
position: relative;
|
||||
display: table-cell;
|
||||
}
|
||||
div[data-control="media-manager"] div[data-control="selection-marker"] {
|
||||
position: absolute;
|
||||
z-index: 50;
|
||||
border: 1px dashed #95a5a6;
|
||||
}
|
||||
div[data-control="media-manager"] .upload-progress {
|
||||
background: #f9f9f9;
|
||||
padding: 0 20px;
|
||||
}
|
||||
div[data-control="media-manager"] .upload-progress h5 {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 13px;
|
||||
color: #2b3e50;
|
||||
font-weight: 600;
|
||||
}
|
||||
div[data-control="media-manager"] .upload-progress h5 span {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
color: #95a5a6;
|
||||
font-size: 15px;
|
||||
}
|
||||
div[data-control="media-manager"] .upload-progress .progress-controls {
|
||||
padding-right: 30px;
|
||||
position: relative;
|
||||
}
|
||||
div[data-control="media-manager"] .upload-progress .progress-controls .controls {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
div[data-control="media-manager"] .upload-progress .progress-controls .controls a {
|
||||
display: block;
|
||||
position: relative;
|
||||
top: 7px;
|
||||
right: 3px;
|
||||
color: #95a5a6;
|
||||
font-size: 16px;
|
||||
cursor: pointer!important;
|
||||
}
|
||||
div[data-control="media-manager"] .upload-progress .progress-controls .controls a:hover {
|
||||
text-decoration: none;
|
||||
color: #0181b9;
|
||||
}
|
||||
div[data-control="media-manager"] .dz-preview {
|
||||
display: none;
|
||||
}
|
||||
body:not(.no-select) div[data-control="media-manager"] .media-list.tiles li:hover .icon-container {
|
||||
background: #4da7e8 !important;
|
||||
border-color: #2581b8;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,11 @@
|
|||
this.afterNavigateBound = this.afterNavigate.bind(this)
|
||||
this.releaseSidebarThumbnailAjaxBound = this.releaseSidebarThumbnailAjax.bind(this)
|
||||
this.replaceSidebarPlaceholderBound = this.replaceSidebarPlaceholder.bind(this)
|
||||
this.uploadFileAddedBound = this.uploadFileAdded.bind(this)
|
||||
this.uploadUpdateTotalProgressBound = this.uploadUpdateTotalProgress.bind(this)
|
||||
this.uploadQueueCompleteBound = this.uploadQueueComplete.bind(this)
|
||||
this.uploadSendingBound = this.uploadSending.bind(this)
|
||||
this.uploadErrorBound = this.uploadError.bind(this)
|
||||
|
||||
// State properties
|
||||
this.selectTimer = null
|
||||
|
|
@ -51,16 +56,24 @@
|
|||
MediaManager.prototype.dispose = function() {
|
||||
this.unregisterHandlers()
|
||||
this.clearSelectTimer()
|
||||
this.disableUploader()
|
||||
|
||||
this.$el = null
|
||||
this.$form = null
|
||||
this.updateSidebarPreviewBound = null
|
||||
this.replacePlaceholderBound = null
|
||||
this.placeholdersUpdatedBound = null
|
||||
this.sidebarPreviewElement = null
|
||||
this.itemListElement = null
|
||||
this.afterNavigateBound = null
|
||||
this.replaceSidebarPlaceholderBound = null
|
||||
this.uploadFileAddedBound = null
|
||||
this.releaseSidebarThumbnailAjaxBound = null
|
||||
this.uploadUpdateTotalProgressBound = null
|
||||
this.uploadQueueCompleteBound = null
|
||||
this.uploadSendingBound = null
|
||||
this.uploadErrorBound = null
|
||||
|
||||
this.sidebarPreviewElement = null
|
||||
this.itemListElement = null
|
||||
this.sidebarThumbnailAjax = null
|
||||
this.selectionMarker = null
|
||||
this.thumbnailQueue = []
|
||||
|
|
@ -123,9 +136,9 @@
|
|||
}).done(this.afterNavigateBound)
|
||||
}
|
||||
|
||||
/*
|
||||
* Selecting
|
||||
*/
|
||||
//
|
||||
// Selecting
|
||||
//
|
||||
|
||||
MediaManager.prototype.clearSelectTimer = function() {
|
||||
if (this.selectTimer == null)
|
||||
|
|
@ -162,9 +175,9 @@
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Navigation
|
||||
*/
|
||||
//
|
||||
// Navigation
|
||||
//
|
||||
|
||||
MediaManager.prototype.gotoFolder = function(path, clearCache) {
|
||||
var data = {
|
||||
|
|
@ -187,9 +200,16 @@
|
|||
this.updateSidebarPreview(true)
|
||||
}
|
||||
|
||||
/*
|
||||
* Sidebar
|
||||
*/
|
||||
MediaManager.prototype.refresh = function() {
|
||||
this.gotoFolder(
|
||||
this.$el.find('[data-type="current-folder"]').val(),
|
||||
true
|
||||
)
|
||||
}
|
||||
|
||||
//
|
||||
// Sidebar
|
||||
//
|
||||
|
||||
MediaManager.prototype.isPreviewSidebarVisible = function() {
|
||||
return true
|
||||
|
|
@ -308,9 +328,9 @@
|
|||
this.sidebarThumbnailAjax = null
|
||||
}
|
||||
|
||||
/*
|
||||
* Thumbnails
|
||||
*/
|
||||
//
|
||||
// Thumbnails
|
||||
//
|
||||
|
||||
MediaManager.prototype.generateThumbnails = function() {
|
||||
this.thumbnailQueue = []
|
||||
|
|
@ -393,9 +413,9 @@
|
|||
this.handleThumbnailQueue()
|
||||
}
|
||||
|
||||
/*
|
||||
* Drag-select
|
||||
*/
|
||||
//
|
||||
// Drag-select
|
||||
//
|
||||
|
||||
MediaManager.prototype.getAbsolutePosition = function(element) {
|
||||
// TODO: refactor to a core library
|
||||
|
|
@ -466,26 +486,108 @@
|
|||
)
|
||||
}
|
||||
|
||||
/*
|
||||
* Uploading
|
||||
*/
|
||||
//
|
||||
// Uploading
|
||||
//
|
||||
|
||||
MediaManager.prototype.initUploader = function() {
|
||||
if (this.itemListElement) {
|
||||
// this.dropzone = new Dropzone(this.itemListElement, uploaderOptions)
|
||||
if (!this.itemListElement)
|
||||
return
|
||||
|
||||
var uploaderOptions = {
|
||||
clickable: this.$el.find('[data-control="upload"]').get(0),
|
||||
method: 'POST',
|
||||
url: window.location,
|
||||
paramName: 'file_data',
|
||||
// fallback: implement method that would set a flag that the uploader is not supported by the browser
|
||||
}
|
||||
|
||||
this.dropzone = new Dropzone(this.$el.get(0), uploaderOptions)
|
||||
this.dropzone.on('addedfile', this.uploadFileAddedBound)
|
||||
this.dropzone.on('totaluploadprogress', this.uploadUpdateTotalProgressBound)
|
||||
this.dropzone.on('queuecomplete', this.uploadQueueCompleteBound)
|
||||
this.dropzone.on('sending', this.uploadSendingBound)
|
||||
this.dropzone.on('error', this.uploadErrorBound)
|
||||
}
|
||||
|
||||
// disable
|
||||
// dropzone.on('error', $.proxy(self.onUploadFail, self))
|
||||
// dropzone.on('success', $.proxy(self.onUploadSuccess, self))
|
||||
// dropzone.on('complete', $.proxy(self.onUploadComplete, self))
|
||||
// dropzone.on('sending', function(file, xhr, formData) {
|
||||
// $.each(self.$form.serializeArray(), function (index, field) {
|
||||
// formData.append(field.name, field.value)
|
||||
// })
|
||||
// self.onUploadStart()
|
||||
// })
|
||||
MediaManager.prototype.disableUploader = function() {
|
||||
if (!this.dropzone)
|
||||
return
|
||||
|
||||
this.dropzone.disable()
|
||||
this.dropzone = null
|
||||
}
|
||||
|
||||
MediaManager.prototype.uploadFileAdded = function() {
|
||||
this.showUploadUi()
|
||||
this.setUploadProgress(0)
|
||||
|
||||
this.$el.find('[data-command="cancel-uploading"]').removeClass('hide')
|
||||
this.$el.find('[data-command="close-uploader"]').addClass('hide')
|
||||
}
|
||||
|
||||
MediaManager.prototype.showUploadUi = function() {
|
||||
this.$el.find('[data-control="upload-ui"]').removeClass('hide')
|
||||
}
|
||||
|
||||
MediaManager.prototype.hideUploadUi = function() {
|
||||
this.$el.find('[data-control="upload-ui"]').addClass('hide')
|
||||
}
|
||||
|
||||
MediaManager.prototype.uploadUpdateTotalProgress = function(uploadProgress, totalBytes, totalBytesSent) {
|
||||
this.setUploadProgress(uploadProgress)
|
||||
|
||||
var fileNumberLabel = this.$el.get(0).querySelector('[data-label="file-number-and-progress"]'),
|
||||
messageTemplate = fileNumberLabel.getAttribute('data-message-template'),
|
||||
fileNumber = this.dropzone.getUploadingFiles().length + this.dropzone.getQueuedFiles().length
|
||||
|
||||
// Don't confuse users with displaying 100%
|
||||
// until the operation finishes. We consider the operation
|
||||
// finished when the Dropzone's 'compete' event triggers -
|
||||
// when the response is received from the server.
|
||||
if (uploadProgress >= 100)
|
||||
uploadProgress = 99
|
||||
|
||||
fileNumberLabel.innerHTML = messageTemplate.replace(':number', fileNumber).replace(':percents', Math.round(uploadProgress) + '%')
|
||||
}
|
||||
|
||||
MediaManager.prototype.setUploadProgress = function(value) {
|
||||
var progresBar = this.$el.get(0).querySelector('[data-control="upload-progress-bar"]')
|
||||
|
||||
progresBar.setAttribute('style', 'width: ' + value + '%')
|
||||
progresBar.setAttribute('class', 'progress-bar')
|
||||
}
|
||||
|
||||
MediaManager.prototype.uploadQueueComplete = function() {
|
||||
var fileNumberLabel = this.$el.get(0).querySelector('[data-label="file-number-and-progress"]'),
|
||||
completeTemplate = fileNumberLabel.getAttribute('data-complete-template'),
|
||||
progresBar = this.$el.get(0).querySelector('[data-control="upload-progress-bar"]')
|
||||
|
||||
fileNumberLabel.innerHTML = completeTemplate;
|
||||
progresBar.setAttribute('class', 'progress-bar progress-bar-success')
|
||||
|
||||
this.$el.find('[data-command="cancel-uploading"]').addClass('hide')
|
||||
this.$el.find('[data-command="close-uploader"]').removeClass('hide')
|
||||
|
||||
this.refresh()
|
||||
}
|
||||
|
||||
MediaManager.prototype.uploadSending = function(file, xhr, formData) {
|
||||
formData.append('path', this.$el.find('[data-type="current-folder"]').val())
|
||||
}
|
||||
|
||||
MediaManager.prototype.uploadCancelAll = function() {
|
||||
this.dropzone.removeAllFiles(true)
|
||||
this.hideUploadUi()
|
||||
}
|
||||
|
||||
MediaManager.prototype.uploadError = function(file, message) {
|
||||
swal({
|
||||
title: 'Error uploading file',
|
||||
text: message,
|
||||
// type: 'error',
|
||||
confirmButtonClass: 'btn-default'
|
||||
})
|
||||
}
|
||||
|
||||
// EVENT HANDLERS
|
||||
|
|
@ -504,18 +606,21 @@
|
|||
}
|
||||
|
||||
MediaManager.prototype.onCommandClick = function(ev) {
|
||||
var command = $(ev.target).data('command')
|
||||
var command = $(ev.currentTarget).data('command')
|
||||
|
||||
switch (command) {
|
||||
case 'refresh' :
|
||||
this.gotoFolder(
|
||||
this.$el.find('[data-type="current-folder"]').val(),
|
||||
true
|
||||
)
|
||||
this.refresh()
|
||||
break;
|
||||
case 'change-view' :
|
||||
this.changeView($(ev.target).data('view'))
|
||||
break;
|
||||
case 'cancel-uploading' :
|
||||
this.uploadCancelAll()
|
||||
break;
|
||||
case 'close-uploader':
|
||||
this.hideUploadUi()
|
||||
break;
|
||||
}
|
||||
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -298,6 +298,7 @@ div[data-control="media-manager"] {
|
|||
|
||||
[data-control="item-list"] {
|
||||
position: relative;
|
||||
display: table-cell;
|
||||
}
|
||||
|
||||
div[data-control="selection-marker"] {
|
||||
|
|
@ -305,6 +306,55 @@ div[data-control="media-manager"] {
|
|||
z-index: 50;
|
||||
border: 1px dashed #95a5a6;
|
||||
}
|
||||
|
||||
.upload-progress {
|
||||
background: @color-body-bg;
|
||||
padding: 0 20px;
|
||||
|
||||
h5 {
|
||||
margin: 0 0 10px 0;
|
||||
font-size: 13px;
|
||||
color: #2b3e50;
|
||||
font-weight: 600;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
margin-left: 10px;
|
||||
color: #95a5a6;
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.progress-controls {
|
||||
padding-right: 30px;
|
||||
position: relative;
|
||||
|
||||
.controls {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
position: relative;
|
||||
top: 7px;
|
||||
right: 3px;
|
||||
color: #95a5a6;
|
||||
font-size: 16px;
|
||||
cursor: pointer!important;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
color: @color-link;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dz-preview {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
body:not(.no-select) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<div data-control="media-manager" class="layout" data-alias="<?= $this->alias ?>">
|
||||
<?= $this->makePartial('toolbar') ?>
|
||||
<?= $this->makePartial('upload-progress') ?>
|
||||
|
||||
<div class="layout-row whiteboard">
|
||||
<div class="layout">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<div class="layout control-toolbar standalone-paddings">
|
||||
<div class="layout-cell">
|
||||
<div class="btn-group offset-right">
|
||||
<button type="button" class="btn btn-primary oc-icon-upload"
|
||||
<button type="button" class="btn btn-primary oc-icon-upload" data-control="upload"
|
||||
><?= e(trans('cms::lang.media.upload')) ?></button>
|
||||
<button type="button" class="btn btn-primary oc-icon-folder"
|
||||
><?= e(trans('cms::lang.media.add_folder')) ?></button>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
<div class="layout-row min-size hide" data-control="upload-ui">
|
||||
<div class="layout">
|
||||
<div class="upload-progress">
|
||||
<h5
|
||||
data-label="file-number-and-progress"
|
||||
data-message-template="<?= e(trans('cms::lang.media.uploading_file_num')) ?> <span>:percents</span>"
|
||||
data-complete-template="<?= e(trans('cms::lang.media.uploading_complete')) ?>"
|
||||
></h5>
|
||||
|
||||
<div class="progress-controls">
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" style="width: 0;" data-control="upload-progress-bar">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
<a href="#" data-command="cancel-uploading"><i class="icon-times-circle" title=""></i></a>
|
||||
<a class="hide" href="#" data-command="close-uploader"><i class="icon-check-circle" title=""></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Loading…
Reference in New Issue