This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Bug 858739 - Add thumbnail backend support. Use direct uploading to

S3/Local file system for DnD
  • Loading branch information...
mjschranz committed May 8, 2013
1 parent 2b6d31d commit 584a81f6264df81e8cf388e26d95f4c5e9fbe5b2
View
@@ -1,122 +0,0 @@
-"use strict";
-
-var IMAGE_DATA_URI_PREFIX_REGEX = "data:image/(jpeg|png);base64,";
-
-var crypto = require( "crypto" );
-
-function ImageFile( dataURI, filename, url ) {
- var _data = new Buffer( dataURI, 'base64' );
- var _hash = crypto.createHash( "sha1" ).update( dataURI, "utf8" ).digest( "hex" );
-
- this.createDBReference = function( dbModel, projectId, callback ) {
- dbModel.build({
- filename: filename,
- url: url,
- project: projectId,
- hash: _hash
- }).save().complete( callback );
- };
-
- this.saveToStore = function( store, callback ) {
- store.write( filename, _data, callback );
- };
-
- this.getJSONMetaData = function() {
- return {
- hash: _hash,
- url: url
- };
- };
-
- Object.defineProperties( this, {
- filename: { value: filename },
- url: { value: url }
- });
-}
-
-function saveImageFilesToStore( store, files, callback ) {
- var finishedItems = 0;
- var errs = [];
-
- function itemCallback( err ) {
- if ( err ) {
- errs.push( err );
- }
-
- if ( ++finishedItems === files.length ) {
- callback( errs.length > 0 ? errs : null );
- }
- }
-
- files.forEach( function( file ) {
- file.saveToStore( store, itemCallback );
- });
-}
-
-function collectTrackEvents( projectData ) {
- var trackEvents = [];
- if ( projectData.media ) {
- projectData.media.forEach( function( media ) {
- if ( media.tracks ) {
- media.tracks.forEach( function( track ) {
- if ( track.trackEvents ) {
- trackEvents = trackEvents.concat( track.trackEvents );
- }
- });
- }
- });
- }
- return trackEvents;
-}
-
-function compareImageReferencesInProject( imageReferences, projectData ) {
- var trackEvents = collectTrackEvents( projectData );
- var unlinkedFiles = [];
-
- imageReferences.forEach( function( imageReference ) {
- for ( var i = 0, l = trackEvents.length; i < l; ++i ) {
- if ( trackEvents[ i ].popcornOptions.src === imageReference.url ) {
- return;
- }
- }
- unlinkedFiles.push( imageReference );
- });
-
- return unlinkedFiles;
-}
-
-function filterProjectDataURIs( inputData, urlGenerator ) {
- var filesToWrite = [],
- regexMatch, file, urlPair;
-
- if ( inputData ) {
-
- collectTrackEvents( inputData ).forEach( function( trackEvent ) {
- if ( trackEvent.popcornOptions && trackEvent.popcornOptions.src ) {
- regexMatch = trackEvent.popcornOptions.src.match( IMAGE_DATA_URI_PREFIX_REGEX );
- if ( regexMatch ) {
- urlPair = urlGenerator();
-
- file = new ImageFile(
- trackEvent.popcornOptions.src.substr( regexMatch[ 0 ].length ),
- urlPair.filename,
- urlPair.url
- );
-
- trackEvent.popcornOptions.src = file.url;
- filesToWrite.push( file );
- }
- }
- });
- }
-
- return filesToWrite;
-}
-
-module.exports = {
- collectTrackEvents: collectTrackEvents,
- compareImageReferencesInProject: compareImageReferencesInProject,
- filterProjectDataURIs: filterProjectDataURIs,
- saveImageFilesToStore: saveImageFilesToStore,
- ImageFile: ImageFile
-};
View
@@ -70,10 +70,14 @@ function LocalFileStore( options ) {
LocalFileStore.prototype = Object.create( BaseFileStore );
-LocalFileStore.prototype.write = function( path, data, callback ) {
+LocalFileStore.prototype.write = function( path, data, contentType, callback ) {
path = Path.join( this.root, this.expand( path ) );
ensurePathExistsSync( Path.dirname( path ) );
+ if ( typeof contentType === "function" ) {
+ callback = contentType;
+ }
+
fs.writeFile( path, data, function( err ) {
if (err) {
callback( err );
@@ -128,15 +132,20 @@ function S3FileStore( options ) {
S3FileStore.prototype = Object.create( BaseFileStore );
-S3FileStore.prototype.write = function( key, data, callback ) {
+S3FileStore.prototype.write = function( key, data, contentType, callback ) {
// If the data we're writing is a string, then we want the byte count in UTF-8
// Otherwise, assume it's already a Buffer object
var contentLength = typeof data === "string" ? Buffer.byteLength( data, 'utf8' ) : data.length;
+ if ( typeof contentType === "function" ) {
+ callback = contentType;
+ contentType = this.contentType;
+ }
+
var headers = {
'x-amz-acl': 'public-read',
'Content-Length': contentLength,
- 'Content-Type': this.contentType
+ 'Content-Type': contentType
};
Object.keys( this.headers ).forEach(function( key ) {
View
@@ -24,6 +24,20 @@ filters = {
crossOriginAccessible: function( req, res, next ) {
res.set( 'Access-Control-Allow-Origin', '*' );
next();
+ },
+ isImage: function( req, res, next ) {
+ var validMimeTypes = [
+ "image/jpeg",
+ "image/png",
+ "image/gif"
+ ],
+ image = req.files.image;
+
+ if ( validMimeTypes.indexOf( image.type ) >= 0 ) {
+ return next();
+ }
+
+ next( new Error( "Upload Failed - Invalid MimeType." ) );
}
};
View
@@ -1,27 +0,0 @@
-"use strict";
-
-module.exports = function(sequelize, DataTypes) {
- return sequelize.define( "Image", {
- id: {
- type: DataTypes.INTEGER,
- primaryKey: true,
- autoIncrement: true
- },
- hash: {
- type: DataTypes.STRING,
- allowNull: false
- },
- url: {
- type: DataTypes.STRING,
- allowNull: false
- },
- filename: {
- type: DataTypes.STRING,
- allowNull: false,
- },
- project: {
- type: DataTypes.INTEGER,
- allowNull: false,
- }
- });
-};
View
@@ -56,6 +56,9 @@ module.exports = function(sequelize, DataTypes) {
},
description: {
type: DataTypes.STRING
+ },
+ thumbnail: {
+ type: DataTypes.STRING
}
});
};
View
@@ -1,7 +1,5 @@
"use strict";
-var datauri = require('./datauri');
-
function defaultDBReadyFunction( err ) {
if ( err ) {
err = Array.isArray( err ) ? err[ 0 ] : err;
@@ -32,7 +30,6 @@ module.exports = function( config, dbReadyFn ) {
var dbOnline = false,
Project = sequelize.import( __dirname + "/models/project" ),
- ImageReference = sequelize.import( __dirname + "/models/image" ),
butterVersion = require( "../package.json" ).version;
sequelize.sync().complete(function( err ) {
@@ -64,61 +61,6 @@ module.exports = function( config, dbReadyFn ) {
return {
- linkImageFilesToProject: function( options, callback ) {
- options = options || {};
- var files = options.files,
- projectId = options.id,
- finishedItems = 0,
- errs = [];
-
- function itemCallback( err ) {
- if ( err ) {
- errs.push( err );
- }
-
- if ( ++finishedItems === files.length ) {
- callback( errs.length > 0 ? errs : null );
- }
- }
-
- Project.find( { where: { id: projectId } } )
- .success( function( project ) {
- if ( project ) {
- files.forEach( function( file ) {
- file.createDBReference( ImageReference, projectId, itemCallback );
- });
- }
- else {
- callback( "Project not found" );
- }
- })
- .error( callback );
- },
-
- createImageReferencesForProject: function( options, callback ) {
- options = options || {};
- var imageFiles = options.files,
- projectId = options.id,
- savedImages = 0,
- errs =[];
-
- imageFiles.forEach( function( imageFile ) {
- ImageReference.build({
- filename: imageFile.filename,
- url: imageFile.url,
- project: projectId
- }).save().complete( function( err ) {
- if ( err ) {
- errs.push( err );
- }
-
- if ( ++savedImages === imageFiles.length ) {
- callback( errs.length > 0 ? errs : null );
- }
- });
- });
- },
-
getSequelizeInstance: function(){
return sequelize;
},
@@ -142,7 +84,8 @@ module.exports = function( config, dbReadyFn ) {
template: data.template,
originalButterVersion: butterVersion,
latestButterVersion: butterVersion,
- remixedFrom: data.remixedFrom
+ remixedFrom: data.remixedFrom,
+ thumbnail: data.thumbnail
});
project.save().complete( callback );
@@ -162,18 +105,7 @@ module.exports = function( config, dbReadyFn ) {
.success(function( project ) {
if ( project ) {
- ImageReference.findAll( { where: { project: pid } } ).complete( function( err, imageReferences ) {
-
- imageReferences.forEach( function( imageReference ) {
- imageReference.destroy();
- });
-
- project.destroy().complete( function( err ) {
- callback( err, imageReferences );
- });
-
- });
-
+ callback( null, project );
} else {
callback( "the project has already been deleted" );
}
@@ -268,23 +200,14 @@ module.exports = function( config, dbReadyFn ) {
description: data.description,
template: data.template,
latestButterVersion: butterVersion,
- remixedFrom: data.remixedFrom
+ remixedFrom: data.remixedFrom,
+ thumbnail: data.thumbnail
})
.error( function( err ) {
callback( err );
})
.success( function( projectUpdateResult ) {
-
- ImageReference.findAll( { where: { project: pid } } ).complete( function( imageReferenceErr, imageReferences ) {
-
- var imagesToDestroy = datauri.compareImageReferencesInProject( imageReferences, projectDataJSON );
-
- imagesToDestroy.forEach( function( imageReference ) {
- imageReference.destroy();
- });
-
- callback( null, projectUpdateResult, imagesToDestroy );
- });
+ callback( null, projectUpdateResult );
});
})
.error(function( error ) {
View
@@ -12,7 +12,7 @@ utils = {
pathToURL: function ( s ) {
return s.replace( /\\/g, '/' );
},
- generateDataURIPair: function() {
+ generateFileName: function() {
var filename = uuid.v4();
return {
filename: filename,
@@ -32,7 +32,7 @@ define( [ "core/eventmanager", "core/media", "util/sanitizer" ],
// Interval for backups, starts first time user clicks Save.
_backupInterval = -1,
- _thumbnail = "/resources/icons/fb-logo.png";
+ _thumbnail = location.protocol + "//" + location.host + "/resources/icons/fb-logo.png";
function invalidate() {
// Project is dirty, needs save, backup
@@ -154,8 +154,8 @@ define([ "editor/editor", "editor/base-editor",
_this.setErrorState( "Sorry, but your browser doesn't support this feature." );
});
- butter.listen( "filetype-unsupported", function invalidType() {
- _this.setErrorState( "Sorry but that file type isn't supported. Please use JPEG or PNG." );
+ butter.listen( "droppable-upload-failed", function failedUpload( e ) {
+ _this.setErrorState( e.data );
});
butter.listen( "projectsaved", function onProjectSaved() {
Oops, something went wrong.

0 comments on commit 584a81f

Please sign in to comment.