get dropzone to render
This commit is contained in:
parent
62023c2c82
commit
c677c37597
11 changed files with 531 additions and 2 deletions
|
@ -11,7 +11,6 @@ export function updateFileContent(name, content) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO make req to server
|
|
||||||
export function createFile(formProps) {
|
export function createFile(formProps) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
|
|
51
client/modules/IDE/actions/uploader.js
Normal file
51
client/modules/IDE/actions/uploader.js
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const s3Bucket = 'http://p5js-web-editor-test.s3.amazonaws.com/';
|
||||||
|
const ROOT_URL = location.href.indexOf('localhost') > 0 ? 'http://localhost:8000/api' : '/api';
|
||||||
|
|
||||||
|
export function dropzoneAcceptCallback(file, done) {
|
||||||
|
file.postData = []; // eslint-disable-line
|
||||||
|
axios.post(`${ROOT_URL}/S3/sign`, {
|
||||||
|
name: file.name,
|
||||||
|
type: file.type,
|
||||||
|
size: file.size,
|
||||||
|
_csrf: document.findElementById('__createPostToken').value
|
||||||
|
},
|
||||||
|
{
|
||||||
|
withCredentials: true
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
file.custom_status = 'ready'; // eslint-disable-line
|
||||||
|
file.postData = response.data; // eslint-disable-line
|
||||||
|
file.s3 = response.data.key; // eslint-disable-line
|
||||||
|
file.previewTemplate.className += ' uploading'; // eslint-disable-line
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(response => {
|
||||||
|
file.custom_status = 'rejected'; // eslint-disable-line
|
||||||
|
if (response.data.responseText && response.data.responseText.message) {
|
||||||
|
done(response.data.responseText.message);
|
||||||
|
}
|
||||||
|
done('error preparing the upload');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dropzoneSendingCallback(file, xhr, formData) {
|
||||||
|
Object.keys(file.postData).forEach(key => {
|
||||||
|
formData.append(key, file.postData[key]);
|
||||||
|
});
|
||||||
|
formData.append('Content-type', '');
|
||||||
|
formData.append('Content-length', '');
|
||||||
|
formData.append('acl', 'public-read');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function dropzoneCompleteCallback(file) {
|
||||||
|
let inputHidden = '<input type="hidden" name="attachments[]" value="';
|
||||||
|
const json = {
|
||||||
|
url: `${s3Bucket}${file.postData.key}`,
|
||||||
|
originalFilename: file.name
|
||||||
|
};
|
||||||
|
console.log(json, JSON.stringify(json), JSON.stringify(json).replace('"', '\\"'));
|
||||||
|
inputHidden += `${window.btoa(JSON.stringify(json))}" />`;
|
||||||
|
document.findElementById('createPost').appendChild(inputHidden);
|
||||||
|
}
|
35
client/modules/IDE/components/FileUploader.js
Normal file
35
client/modules/IDE/components/FileUploader.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import React from 'react';
|
||||||
|
import Dropzone from 'dropzone';
|
||||||
|
const s3Bucket = 'http://p5js-web-editor-test.s3.amazonaws.com/';
|
||||||
|
import { dropzoneAcceptCallback,
|
||||||
|
dropzoneSendingCallback,
|
||||||
|
dropzoneCompleteCallback } from '../actions/uploader';
|
||||||
|
|
||||||
|
class FileUploader extends React.Component {
|
||||||
|
componentDidMount() {
|
||||||
|
Dropzone.options.uploader = {
|
||||||
|
url: s3Bucket,
|
||||||
|
method: 'post',
|
||||||
|
autoProcessQueue: true,
|
||||||
|
clickable: true,
|
||||||
|
maxFiles: 1,
|
||||||
|
parallelUploads: 1,
|
||||||
|
maxFilesize: 10, // in mb
|
||||||
|
maxThumbnailFilesize: 8, // 3MB
|
||||||
|
thumbnailWidth: 150,
|
||||||
|
thumbnailHeight: 150,
|
||||||
|
acceptedMimeTypes: 'image/bmp,image/gif,image/jpg,image/jpeg,image/png',
|
||||||
|
accept: dropzoneAcceptCallback,
|
||||||
|
sending: dropzoneSendingCallback,
|
||||||
|
complete: dropzoneCompleteCallback
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div id="uploader" className="uploader dropzone"></div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default FileUploader;
|
|
@ -7,6 +7,8 @@ import classNames from 'classnames';
|
||||||
import InlineSVG from 'react-inlinesvg';
|
import InlineSVG from 'react-inlinesvg';
|
||||||
const exitUrl = require('../../../images/exit.svg');
|
const exitUrl = require('../../../images/exit.svg');
|
||||||
|
|
||||||
|
import FileUploader from './FileUploader';
|
||||||
|
|
||||||
// At some point this will probably be generalized to a generic modal
|
// At some point this will probably be generalized to a generic modal
|
||||||
// in which you can insert different content
|
// in which you can insert different content
|
||||||
// but for now, let's just make this work
|
// but for now, let's just make this work
|
||||||
|
@ -26,6 +28,8 @@ function NewFileModal(props) {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<NewFileForm {...props} />
|
<NewFileForm {...props} />
|
||||||
|
<p className="modal__divider">OR</p>
|
||||||
|
<FileUploader />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
.modal-content {
|
.modal-content {
|
||||||
border: 1px solid $light-modal-border-color;
|
border: 1px solid $light-modal-border-color;
|
||||||
background-color: $light-button-background-color;
|
background-color: $light-button-background-color;
|
||||||
height: #{150 / $base-font-size}rem;
|
height: #{400 / $base-font-size}rem;
|
||||||
width: #{400 / $base-font-size}rem;
|
width: #{400 / $base-font-size}rem;
|
||||||
padding: #{20 / $base-font-size}rem;
|
padding: #{20 / $base-font-size}rem;
|
||||||
}
|
}
|
||||||
|
@ -34,3 +34,13 @@
|
||||||
.new-file-form__name-input {
|
.new-file-form__name-input {
|
||||||
margin-right: #{10 / $base-font-size}rem;
|
margin-right: #{10 / $base-font-size}rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal__divider {
|
||||||
|
text-align: center;
|
||||||
|
margin: #{20 / $base-font-size}rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uploader {
|
||||||
|
height: #{200 / $base-font-size}rem;
|
||||||
|
width: 100%;
|
||||||
|
}
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
@import 'vendors/codemirror';
|
@import 'vendors/codemirror';
|
||||||
@import 'vendors/lint';
|
@import 'vendors/lint';
|
||||||
|
@import 'vendors/dropzone';
|
||||||
|
|
||||||
@import 'components/p5-widget-codemirror-theme';
|
@import 'components/p5-widget-codemirror-theme';
|
||||||
@import 'components/editor';
|
@import 'components/editor';
|
||||||
|
|
388
client/styles/vendors/_dropzone.scss
vendored
Normal file
388
client/styles/vendors/_dropzone.scss
vendored
Normal file
|
@ -0,0 +1,388 @@
|
||||||
|
/*
|
||||||
|
* The MIT License
|
||||||
|
* Copyright (c) 2012 Matias Meno <m@tias.me>
|
||||||
|
*/
|
||||||
|
@-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-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; }
|
|
@ -67,6 +67,7 @@
|
||||||
"cookie-parser": "^1.4.1",
|
"cookie-parser": "^1.4.1",
|
||||||
"csslint": "^0.10.0",
|
"csslint": "^0.10.0",
|
||||||
"dotenv": "^2.0.0",
|
"dotenv": "^2.0.0",
|
||||||
|
"dropzone": "^4.3.0",
|
||||||
"escape-string-regexp": "^1.0.5",
|
"escape-string-regexp": "^1.0.5",
|
||||||
"eslint-loader": "^1.3.0",
|
"eslint-loader": "^1.3.0",
|
||||||
"express": "^4.13.4",
|
"express": "^4.13.4",
|
||||||
|
@ -77,6 +78,7 @@
|
||||||
"jszip": "^3.0.0",
|
"jszip": "^3.0.0",
|
||||||
"moment": "^2.14.1",
|
"moment": "^2.14.1",
|
||||||
"mongoose": "^4.4.16",
|
"mongoose": "^4.4.16",
|
||||||
|
"node-uuid": "^1.4.7",
|
||||||
"passport": "^0.3.2",
|
"passport": "^0.3.2",
|
||||||
"passport-github": "^1.1.0",
|
"passport-github": "^1.1.0",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
|
@ -88,6 +90,7 @@
|
||||||
"redux": "^3.5.2",
|
"redux": "^3.5.2",
|
||||||
"redux-form": "^5.2.5",
|
"redux-form": "^5.2.5",
|
||||||
"redux-thunk": "^2.1.0",
|
"redux-thunk": "^2.1.0",
|
||||||
|
"s3-policy": "^0.2.0",
|
||||||
"shortid": "^2.2.6",
|
"shortid": "^2.2.6",
|
||||||
"srcdoc-polyfill": "^0.2.0",
|
"srcdoc-polyfill": "^0.2.0",
|
||||||
"throttle-debounce": "^1.0.1"
|
"throttle-debounce": "^1.0.1"
|
||||||
|
|
28
server/controllers/aws.controller.js
Normal file
28
server/controllers/aws.controller.js
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import uuid from 'node-uuid';
|
||||||
|
import policy from 's3-policy';
|
||||||
|
|
||||||
|
function getExtension(filename) {
|
||||||
|
const i = filename.lastIndexOf('.');
|
||||||
|
return (i < 0) ? '' : filename.substr(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function signS3(req, res) {
|
||||||
|
const fileExtension = getExtension(req.body.name),
|
||||||
|
filename = uuid.v4() + fileExtension,
|
||||||
|
acl = 'public-read',
|
||||||
|
p = policy({
|
||||||
|
acl: acl,
|
||||||
|
secret: process.env.AWS_SECRET_KEY,
|
||||||
|
length: 5000000, // in bytes?
|
||||||
|
bucket: process.env.S3_BUCKET,
|
||||||
|
key: filename,
|
||||||
|
expires: new Date(Date.now() + 60000),
|
||||||
|
}),
|
||||||
|
result = {
|
||||||
|
'AWSAccessKeyId': process.env.AWS_ACCESS_KEY,
|
||||||
|
'key': filename,
|
||||||
|
'policy': p.policy,
|
||||||
|
'signature': p.signature
|
||||||
|
};
|
||||||
|
return res.json(result);
|
||||||
|
};
|
8
server/routes/aws.routes.js
Normal file
8
server/routes/aws.routes.js
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
import { Router } from 'express';
|
||||||
|
import * as AWSController from '../controllers/aws.controller';
|
||||||
|
|
||||||
|
const router = new Router();
|
||||||
|
|
||||||
|
router.route('/S3/sign').post(AWSController.signS3);
|
||||||
|
|
||||||
|
export default router;
|
|
@ -28,6 +28,7 @@ import users from './routes/user.routes';
|
||||||
import sessions from './routes/session.routes';
|
import sessions from './routes/session.routes';
|
||||||
import projects from './routes/project.routes';
|
import projects from './routes/project.routes';
|
||||||
import files from './routes/file.routes';
|
import files from './routes/file.routes';
|
||||||
|
import aws from './routes/aws.routes';
|
||||||
import serverRoutes from './routes/server.routes';
|
import serverRoutes from './routes/server.routes';
|
||||||
|
|
||||||
// Body parser, cookie parser, sessions, serve public assets
|
// Body parser, cookie parser, sessions, serve public assets
|
||||||
|
@ -57,6 +58,7 @@ app.use('/api', users);
|
||||||
app.use('/api', sessions);
|
app.use('/api', sessions);
|
||||||
app.use('/api', projects);
|
app.use('/api', projects);
|
||||||
app.use('/api', files);
|
app.use('/api', files);
|
||||||
|
app.use('/api', aws);
|
||||||
// this is supposed to be TEMPORARY -- until i figure out
|
// this is supposed to be TEMPORARY -- until i figure out
|
||||||
// isomorphic rendering
|
// isomorphic rendering
|
||||||
app.use('/', serverRoutes);
|
app.use('/', serverRoutes);
|
||||||
|
|
Loading…
Reference in a new issue