Implemented file uploading

This commit is contained in:
alekseybobkov 2015-03-15 21:54:32 -07:00
parent 78ad303236
commit 44c08b76f9
16 changed files with 6209 additions and 1140 deletions

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -257,6 +257,7 @@ table.table.data {
&.clickable {
cursor: pointer;
.user-select(none);
}
td.column-compact {
padding: 0;

View File

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

View File

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

View File

@ -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.
*

View File

@ -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() ?>

View File

@ -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'
]
];

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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