diff --git a/.gitignore b/.gitignore index 191af89..1419973 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .eslintcache .idea +composer.phar dist lib node_modules diff --git a/README.md b/README.md index 4a38595..3c0606c 100644 --- a/README.md +++ b/README.md @@ -34,13 +34,11 @@ These combine many focused components that provide style (which can be adjusted These wrap a Fine Uploader instance for use in React Fine Uploader. They provide additional features such as the ability to dynamically register multiple event/callback listeners. All individual and higher-order/focused components require you to pass a constructed wrapper class instance. +More information, such as examples and API documentation, can be found in the README of the [fine-uploader-wrappers project](https://github.com/FineUploader/fine-uploader-wrappers). + ### Quick Reference - [Installing](#installing) -- [Wrapper Classes](#wrapper-classes) - - [Azure](#azure) - upload files directly to Azure storage - - [S3](#s3) - upload files to directly to an Amazon Simple Storage Service (S3) bucket. Your server must sign requests using a private key. - - [Traditional](#traditional) - upload files to a server you created and control. - [High-level Components](#high-level-components) - [``](#gallery-) - [Low-level Components](#low-level-components) @@ -60,195 +58,6 @@ These wrap a Fine Uploader instance for use in React Fine Uploader. They provide 0.1.0 is the first version of react-fine-uploader published on npm. Two dependencies that you will need to install yourself: an A+/Promise spec compliant polyfill (for IE11) and React (which is a peer dependency). Simply `npm install react-fine-uploader` and see the documentation for your specific integration instructions (based on your needs). -### Wrapper Classes - -#### Azure - -This enables you to upload to Azure directly. Your server must provide signature and done endpoints. The Azure uploading workflow is documented on the [Azure feature page](http://docs.fineuploader.com/branch/master/features/azure.html). Some examples servers can be found in the [server-examples repository](https://github.com/FineUploader/server-examples). - -##### `constructor({ options })` - -When creating a new instance of the Azure endpoint wrapper class, pass in an object that mirrors the format of the [Fine Uploader Azure Core options object](http://docs.fineuploader.com/branch/master/api/options-azure.html). This options property is entirely optional. - -```javascript -import FineUploaderAzure from 'react-fine-uploader/wrappers/azure' - -const uploader = new FineUploaderAzure({ - options: { - signature: { - endpoint: '/upload/signature', - }, - uploadSuccess: { - endpoint: '/upload/done', - } - } -}) -``` - -##### `on(eventName, handlerFunction)` - -Register a new callback/event handler. The `eventName` can be formatted with _or_ without the 'on' prefix. If you do use the 'on', prefix, be sure to follow lower-camel-case exactly ('onSubmit', not 'onsubmit'). If a handler has already been registered for this event, yours will be added to the "pipeline" for this event. If a previously registered handler for this event fails for some reason or returns `false`, you handler will _not_ be called. Your handler function may return a `Promise` if it is [listed as an event type that supports promissory/thenable return values](http://docs.fineuploader.com/branch/master/features/async-tasks-and-promises.html#promissory-callbacks). - -```javascript -uploader.on('complete', (id, name, response) => { - // handle completed upload -}) -``` - -##### `off(eventName, handlerFunction)` - -Unregister a previously registered callback/event handler. Same rules for `eventName` as the `on` method apply here. The `handlerFunction` _must_ be the _exact_ `handlerFunction` passed to the `on` method when you initially registered said function. - -```javascript -const completeHandler = (id, name, response) => { - // handle completed upload -}) - -uploader.on('complete', completeHandler) - -// ...later -uploader.off('complete', completeHandler) -``` - -##### `options` - -The `options` property you used when constructing a new instance, sans any `callbacks`. - -##### `methods` - -Use this property to access any [core API methods exposed by Fine Uploader Azure](http://docs.fineuploader.com/branch/master/api/methods-azure.html). - -```javascript -uploader.methods.getResumableFilesData(myFiles) -``` - - -#### S3 - -Use the traditional endpoint wrapper class if you would like to upload files directly to an Amazon Simple Storage Service (S3 bucket). Your server must be able to sign requests sent by Fine Uploader. If you enable the delete file feature, your server must handle these as well. You can read more about [S3 server requests in the documentation](http://docs.fineuploader.com/branch/master/endpoint_handlers/amazon-s3.html). The S3 uploading workflow is documented on the [S3 feature page](http://docs.fineuploader.com/branch/master/features/s3.html). Some examples servers can be found in the [server-examples repository](https://github.com/FineUploader/server-examples). - -##### `constructor({ options })` - -When creating a new instance of the S3 endpoint wrapper class, pass in an object that mirrors the format of the [Fine Uploader S3 Core options object](http://docs.fineuploader.com/branch/master/api/options-s3.html). You may also include a `callbacks` property to include any initial [core callback handlers](http://docs.fineuploader.com/branch/master/api/events-s3.html) that you might need. This options property is entirely optional though :laughing:. - -```javascript -import FineUploaderS3 from 'react-fine-uploader/wrappers/s3' - -const uploader = new FineUploaderS3({ - options: { - request: { - endpoint: "http://fineuploadertest.s3.amazonaws.com", - accessKey: "AKIAIXVR6TANOGNBGANQ" - }, - signature: { - endpoint: "/vendor/fineuploader/php-s3-server/endpoint.php" - } - } -}) -``` - -##### `on(eventName, handlerFunction)` - -Register a new callback/event handler. The `eventName` can be formatted with _or_ without the 'on' prefix. If you do use the 'on', prefix, be sure to follow lower-camel-case exactly ('onSubmit', not 'onsubmit'). If a handler has already been registered for this event, yours will be added to the "pipeline" for this event. If a previously registered handler for this event fails for some reason or returns `false`, you handler will _not_ be called. Your handler function may return a `Promise` if it is [listed as an event type that supports promissory/thenable return values](http://docs.fineuploader.com/branch/master/features/async-tasks-and-promises.html#promissory-callbacks). - -```javascript -uploader.on('complete', (id, name, response) => { - // handle completed upload -}) -``` - -##### `off(eventName, handlerFunction)` - -Unregister a previously registered callback/event handler. Same rules for `eventName` as the `on` method apply here. The `handlerFunction` _must_ be the _exact_ `handlerFunction` passed to the `on` method when you initially registered said function. - -```javascript -const completeHandler = (id, name, response) => { - // handle completed upload -}) - -uploader.on('complete', completeHandler) - -// ...later -uploader.off('complete', completeHandler) -``` - -##### `options` - -The `options` property you used when constructing a new instance, sans any `callbacks`. - -##### `methods` - -Use this property to access any [core API methods exposed by Fine Uploader S3](http://docs.fineuploader.com/branch/master/api/methods-s3.html). - -```javascript -uploader.methods.addFiles(myFiles) -uploader.methods.deleteFile(3) -``` - -#### Traditional - -Use the traditional endpoint wrapper class if you would like to upload files to a server you control. Your server must handle _all_ requests sent by Fine Uploader, such as upload, delete file (optional), and chunking success (optional). You can read more about [traditional server requests in the documentation](http://docs.fineuploader.com/branch/master/endpoint_handlers/traditional.html). Some examples servers can be found in the [server-examples repository](https://github.com/FineUploader/server-examples). - -##### `constructor({ options })` - -When creating a new instance of the traditional endpoint wrapper class, pass in an object that mirrors the format of the [Fine Uploader Core options object](http://docs.fineuploader.com/branch/master/api/options.html). You may also include a `callbacks` property to include any initial [core callback handlers](http://docs.fineuploader.com/branch/master/api/events.html) that you might need. This options property is entirely optional. - -```javascript -import FineUploaderTraditional from 'react-fine-uploader' - -const uploader = new FineUploaderTraditional({ - options: { - request: { - endpoint: 'my/upload/endpoint' - }, - callbacks: { - onComplete: (id, name, response) => { - // handle completed upload - } - } - } -}) -``` - -##### `on(eventName, handlerFunction)` - -Register a new callback/event handler. The `eventName` can be formatted with _or_ without the 'on' prefix. If you do use the 'on', prefix, be sure to follow lower-camel-case exactly ('onSubmit', not 'onsubmit'). If a handler has already been registered for this event, yours will be added to the "pipeline" for this event. If a previously registered handler for this event fails for some reason or returns `false`, you handler will _not_ be called. Your handler function may return a `Promise` iff it is [listed as an event type that supports promissory/thenable return values](http://docs.fineuploader.com/branch/master/features/async-tasks-and-promises.html#promissory-callbacks). - -```javascript -uploader.on('complete', (id, name, response) => { - // handle completed upload -}) -``` - -##### `off(eventName, handlerFunction)` - -Unregister a previously registered callback/event handler. Same rules for `eventName` as the `on` method apply here. The `handlerFunction` _must_ be the _exact_ `handlerFunction` passed to the `on` method when you initially registered said function. - -```javascript -const completeHandler = (id, name, response) => { - // handle completed upload -}) - -uploader.on('complete', completeHandler) - -// ...later -uploader.off('complete', completeHandler) -``` - -##### `options` - -The `options` property you used when constructing a new instance, sans any `callbacks`. - -##### `methods` - -Use this property to access any [core API methods exposed by Fine Uploader](http://docs.fineuploader.com/branch/master/api/methods.html). - -```javascript -uploader.methods.addFiles(myFiles) -uploader.methods.deleteFile(3) -``` - - ### High-level Components #### `` @@ -304,11 +113,11 @@ For example, if you render a `` component using the following code: ```js import React, { Component } from 'react' -import FineUploaderTraditional from 'react-fine-uploader' -import Gallery from 'react-fine-uploader/components/gallery' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import Gallery from 'react-fine-uploader' // ...or load this specific CSS file using a tag in your document -import 'react-fine-uploader/components/gallery/gallery.css' +import 'react-fine-uploader/gallery/gallery.css' const uploader = new FineUploaderTraditional({ options: { @@ -371,9 +180,9 @@ The example below will include a cancel button for each submitted file along wit import React, { Component } from 'react' import ReactDOM from 'react-dom' -import CancelButton from 'react-fine-uploader/components/cancel-button' -import FineUploaderTraditional from 'react-fine-uploader' -import Thumbnail from 'react-fine-uploader/components/thumbnail' +import CancelButton from 'react-fine-uploader/cancel-button' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import Thumbnail from 'react-fine-uploader/thumbnail' const uploader = new FineUploader({ options: { @@ -457,9 +266,9 @@ The example below will include a delete button for each submitted file along wit ```javascript import React, { Component } from 'react' -import DeleteButton from 'react-fine-uploader/components/delete-button' -import FineUploaderTraditional from 'react-fine-uploader' -import Thumbnail from 'react-fine-uploader/components/thumbnail' +import DeleteButton from 'react-fine-uploader/delete-button' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import Thumbnail from 'react-fine-uploader/thumbnail' const uploader = new FineUploader({ options: { @@ -552,8 +361,8 @@ A _very_ simple but completely functional and effective use of the ` import React from 'react' import ReactDOM from 'react-dom' -import FileInput from 'react-fine-uploader/components/dropzone' -import FineUploaderTraditional from 'react-fine-uploader' +import FileInput from 'react-fine-uploader/dropzone' +import FineUploaderTraditional from 'fine-uploader-wrappers' const uploader = new FineUploaderTraditional({ options: { @@ -595,8 +404,8 @@ Note: This assumes you have [the Ionicons CSS file](http://ionicons.com/#cdn) lo import React from 'react' import ReactDOM from 'react-dom' -import FileInput from 'react-fine-uploader/components/file-input' -import FineUploaderTraditional from 'react-fine-uploader' +import FileInput from 'react-fine-uploader/file-input' +import FineUploaderTraditional from 'fine-uploader-wrappers' const uploader = new FineUploaderTraditional({ options: { @@ -637,8 +446,8 @@ Note: This assumes you have additional components or code to allow files to actu ```javascript import React, { Component } from 'react' -import FineUploaderTraditional from 'react-fine-uploader' -import Filename from 'react-fine-uploader/components/filename' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import Filename from 'react-fine-uploader/filename' const uploader = new FineUploader({ options: { @@ -706,8 +515,8 @@ Note: This assumes you have additional components or code to allow files to actu ```javascript import React, { Component } from 'react' -import FineUploaderTraditional from 'react-fine-uploader' -import Filesize from 'react-fine-uploader/components/filesize' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import Filesize from 'react-fine-uploader/filesize' const uploader = new FineUploader({ options: { @@ -787,9 +596,9 @@ The example below will include a pause/resume button for each submitted file alo ```javascript import React, { Component } from 'react' -import FineUploaderTraditional from 'react-fine-uploader' -import PauseResumeButton from 'react-fine-uploader/components/PauseResume-button' -import Thumbnail from 'react-fine-uploader/components/thumbnail' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import PauseResumeButton from 'react-fine-uploader/pause-resume-button' +import Thumbnail from 'react-fine-uploader/thumbnail' const uploader = new FineUploader({ options: { @@ -881,9 +690,9 @@ The example below will include a retry button for each submitted file along with ```javascript import React, { Component } from 'react' -import FineUploaderTraditional from 'react-fine-uploader' -import RetryButton from 'react-fine-uploader/components/retry-button' -import Thumbnail from 'react-fine-uploader/components/thumbnail' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import RetryButton from 'react-fine-uploader/retry-button' +import Thumbnail from 'react-fine-uploader/thumbnail' const uploader = new FineUploader({ options: { @@ -959,9 +768,9 @@ Note: This assumes you have additional components or code to allow files to actu ```javascript import React, { Component } from 'react' -import FineUploaderTraditional from 'react-fine-uploader' -import Status from 'react-fine-uploader/components/filesize' -import Thumbnail from 'react-fine-uploader/components/thumbnail' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import Status from 'react-fine-uploader/filesize' +import Thumbnail from 'react-fine-uploader/thumbnail' const uploader = new FineUploader({ options: { @@ -1027,8 +836,8 @@ Note: This assumes you have additional components or code to allow files to actu ```javascript import React, { Component } from 'react' -import FineUploaderTraditional from 'react-fine-uploader' -import Thumbnail from 'react-fine-uploader/components/thumbnail' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import Thumbnail from 'react-fine-uploader/thumbnail' const uploader = new FineUploader({ options: { diff --git a/config/webpack.config.js b/config/webpack.config.js index 20cb426..8a95a93 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -3,10 +3,6 @@ const isProduction = process.env.NODE_ENV === 'production'; const path = require('path') module.exports = { - entry: { - 'traditional-wrapper': [path.resolve('src/wrappers/traditional.js')], - 'file-input': [path.resolve('src/components/file-input/styleable-element.jsx')] - }, output: { path: path.resolve('lib'), filename: `[name].${isProduction ? 'min.js' : '.js'}` diff --git a/package.json b/package.json index 1177048..ffda0b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-fine-uploader", - "version": "0.4.0", + "version": "0.5.0", "license": "MIT", "description": "React UI components for using Fine Uploader in a React-based project.", "author": { @@ -19,13 +19,14 @@ "upload", "widget" ], - "main": "wrappers/traditional.js", + "main": "gallery/index.js", "peerDependencies": { "react": "0.14.x || 15.x.x", "react-addons-css-transition-group": "0.14.x || 15.x.x" }, "dependencies": { "fine-uploader": ">=5.11.10 <6.0.0", + "fine-uploader-wrappers": "0.1.1", "object-assign": "4.1.1" }, "devDependencies": { @@ -58,19 +59,19 @@ "react-addons-test-utils": "latest", "react-dom": "latest", "style-loader": "latest", - "webpack": "latest", + "webpack": "1.14.0", "webpack-node-externals": "latest" }, "engines": { "node": ">=5.0.0" }, "scripts": { - "build": "rm -rf lib && mkdir -p lib && cp -pR src/components lib && cp -pR src/wrappers lib && babel lib --out-dir lib && find lib -type f -name '*.jsx' -delete", + "build": "rm -rf lib && mkdir -p lib && cp -pR src/ lib && babel lib --out-dir lib && find lib -type f -name '*.jsx' -delete", "lint": "eslint src/. --ext .js,.jsx --cache", "manual-test": "webpack --config config/webpack.manual-test.config.js --watch --display-error-details", "push-to-npm": "cp package.json README.md LICENSE lib && (cd lib ; npm publish)", "release": "npm run test && npm run build && npm run push-to-npm", - "start": "(. src/test/manual/s3keys.sh; php -S 0.0.0.0:9090 -t src/test/manual -c src/test/manual/php.ini)", + "start": "(php -S 0.0.0.0:9090 -t src/test/manual -c src/test/manual/php.ini)", "start-no-s3": "php -S 0.0.0.0:9090 -t src/test/manual -c src/test/manual/php.ini", "test": "npm run lint && if [ $CI ]; then karma start config/karma.conf; else karma start config/karma.dev.conf; fi" } diff --git a/src/components/cancel-button.jsx b/src/cancel-button.jsx similarity index 100% rename from src/components/cancel-button.jsx rename to src/cancel-button.jsx diff --git a/src/components/delete-button.jsx b/src/delete-button.jsx similarity index 100% rename from src/components/delete-button.jsx rename to src/delete-button.jsx diff --git a/src/components/dropzone.jsx b/src/dropzone.jsx similarity index 100% rename from src/components/dropzone.jsx rename to src/dropzone.jsx diff --git a/src/components/file-input/index.jsx b/src/file-input/index.jsx similarity index 100% rename from src/components/file-input/index.jsx rename to src/file-input/index.jsx diff --git a/src/components/file-input/styleable-element.jsx b/src/file-input/styleable-element.jsx similarity index 100% rename from src/components/file-input/styleable-element.jsx rename to src/file-input/styleable-element.jsx diff --git a/src/components/filename.jsx b/src/filename.jsx similarity index 100% rename from src/components/filename.jsx rename to src/filename.jsx diff --git a/src/components/filesize.jsx b/src/filesize.jsx similarity index 100% rename from src/components/filesize.jsx rename to src/filesize.jsx diff --git a/src/components/gallery/gallery.css b/src/gallery/gallery.css similarity index 100% rename from src/components/gallery/gallery.css rename to src/gallery/gallery.css diff --git a/src/components/gallery/index.jsx b/src/gallery/index.jsx similarity index 100% rename from src/components/gallery/index.jsx rename to src/gallery/index.jsx diff --git a/src/components/gallery/pause-icon.jsx b/src/gallery/pause-icon.jsx similarity index 100% rename from src/components/gallery/pause-icon.jsx rename to src/gallery/pause-icon.jsx diff --git a/src/components/gallery/play-icon.jsx b/src/gallery/play-icon.jsx similarity index 100% rename from src/components/gallery/play-icon.jsx rename to src/gallery/play-icon.jsx diff --git a/src/components/gallery/upload-failed-icon.jsx b/src/gallery/upload-failed-icon.jsx similarity index 100% rename from src/components/gallery/upload-failed-icon.jsx rename to src/gallery/upload-failed-icon.jsx diff --git a/src/components/gallery/upload-icon.jsx b/src/gallery/upload-icon.jsx similarity index 100% rename from src/components/gallery/upload-icon.jsx rename to src/gallery/upload-icon.jsx diff --git a/src/components/gallery/upload-success-icon.jsx b/src/gallery/upload-success-icon.jsx similarity index 100% rename from src/components/gallery/upload-success-icon.jsx rename to src/gallery/upload-success-icon.jsx diff --git a/src/components/gallery/x-icon.jsx b/src/gallery/x-icon.jsx similarity index 100% rename from src/components/gallery/x-icon.jsx rename to src/gallery/x-icon.jsx diff --git a/src/components/pause-resume-button.jsx b/src/pause-resume-button.jsx similarity index 100% rename from src/components/pause-resume-button.jsx rename to src/pause-resume-button.jsx diff --git a/src/components/progress-bar.jsx b/src/progress-bar.jsx similarity index 100% rename from src/components/progress-bar.jsx rename to src/progress-bar.jsx diff --git a/src/components/retry-button.jsx b/src/retry-button.jsx similarity index 100% rename from src/components/retry-button.jsx rename to src/retry-button.jsx diff --git a/src/components/status.jsx b/src/status.jsx similarity index 100% rename from src/components/status.jsx rename to src/status.jsx diff --git a/src/test/manual/composer.json b/src/test/manual/composer.json index 2f550fb..203c19f 100644 --- a/src/test/manual/composer.json +++ b/src/test/manual/composer.json @@ -1,6 +1,6 @@ { "require": { - "fineuploader/php-traditional-server": "1.2.0", + "fineuploader/php-traditional-server": "1.2.1", "fineuploader/php-s3-server": "1.1.0" } } diff --git a/src/test/manual/tester.jsx b/src/test/manual/tester.jsx index 5e5f20d..491c538 100644 --- a/src/test/manual/tester.jsx +++ b/src/test/manual/tester.jsx @@ -1,10 +1,10 @@ import React, { Component } from 'react' -import Gallery from 'lib/components/gallery' -import S3FineUploader from 'lib/wrappers/s3' -import TraditionalFineUploader from 'lib/wrappers/traditional' +import Gallery from 'lib/gallery' +import S3FineUploader from 'fine-uploader-wrappers/s3' +import TraditionalFineUploader from 'fine-uploader-wrappers' -import 'lib/components/gallery/gallery.css' +import 'lib/gallery/gallery.css' const traditionalUploader = new TraditionalFineUploader({ options: { diff --git a/src/test/unit/components/cancel-button.spec.jsx b/src/test/unit/cancel-button.spec.jsx similarity index 96% rename from src/test/unit/components/cancel-button.spec.jsx rename to src/test/unit/cancel-button.spec.jsx index e0e00c8..c61e7c9 100644 --- a/src/test/unit/components/cancel-button.spec.jsx +++ b/src/test/unit/cancel-button.spec.jsx @@ -1,8 +1,8 @@ import React from 'react' import TestUtils from 'react-addons-test-utils' -import FineUploaderTraditional from 'src/wrappers/traditional' -import CancelButton from 'src/components/cancel-button' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import CancelButton from 'src/cancel-button' const sampleBlob = new Blob(['hi!'], { type : 'text/plain' }) diff --git a/src/test/unit/components/delete-button.spec.jsx b/src/test/unit/delete-button.spec.jsx similarity index 96% rename from src/test/unit/components/delete-button.spec.jsx rename to src/test/unit/delete-button.spec.jsx index b15b669..15ec471 100644 --- a/src/test/unit/components/delete-button.spec.jsx +++ b/src/test/unit/delete-button.spec.jsx @@ -1,8 +1,8 @@ import React from 'react' import TestUtils from 'react-addons-test-utils' -import DeleteButton from 'src/components/delete-button' -import FineUploaderTraditional from 'src/wrappers/traditional' +import DeleteButton from 'src/delete-button' +import FineUploaderTraditional from 'fine-uploader-wrappers' describe('', () => { const getButton = Component => ( diff --git a/src/test/unit/components/file-input/file-input.spec.jsx b/src/test/unit/file-input/file-input.spec.jsx similarity index 95% rename from src/test/unit/components/file-input/file-input.spec.jsx rename to src/test/unit/file-input/file-input.spec.jsx index 4b254fb..432cc9c 100644 --- a/src/test/unit/components/file-input/file-input.spec.jsx +++ b/src/test/unit/file-input/file-input.spec.jsx @@ -1,7 +1,7 @@ import React from 'react' import TestUtils from 'react-addons-test-utils' -import FileInput from 'src/components/file-input' +import FileInput from 'src/file-input' class DummyStylableElement extends React.Component { render() { diff --git a/src/test/unit/components/file-input/styleable-element.spec.jsx b/src/test/unit/file-input/styleable-element.spec.jsx similarity index 93% rename from src/test/unit/components/file-input/styleable-element.spec.jsx rename to src/test/unit/file-input/styleable-element.spec.jsx index cc9f504..2f817aa 100644 --- a/src/test/unit/components/file-input/styleable-element.spec.jsx +++ b/src/test/unit/file-input/styleable-element.spec.jsx @@ -2,7 +2,7 @@ import React from 'react' import TestUtils from 'react-addons-test-utils' import { wrapStatelessComponent } from 'test/utils' -import StyleableElement from 'src/components/file-input/styleable-element' +import StyleableElement from 'src/file-input/styleable-element' describe('', () => { const WrappedStyleableElement = wrapStatelessComponent(StyleableElement) diff --git a/src/test/unit/components/filename.spec.jsx b/src/test/unit/filename.spec.jsx similarity index 92% rename from src/test/unit/components/filename.spec.jsx rename to src/test/unit/filename.spec.jsx index 313796a..efd1d61 100644 --- a/src/test/unit/components/filename.spec.jsx +++ b/src/test/unit/filename.spec.jsx @@ -1,8 +1,8 @@ import React from 'react' import TestUtils from 'react-addons-test-utils' -import FineUploaderTraditional from 'src/wrappers/traditional' -import Filename from 'src/components/filename' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import Filename from 'src/filename' const sampleBlob = new Blob(['hi!'], { type : 'text/plain' }) const sampleBlobWrapper = { blob: sampleBlob, name: 'test' } diff --git a/src/test/unit/components/filesize.spec.jsx b/src/test/unit/filesize.spec.jsx similarity index 97% rename from src/test/unit/components/filesize.spec.jsx rename to src/test/unit/filesize.spec.jsx index 067b3d1..23b2c26 100644 --- a/src/test/unit/components/filesize.spec.jsx +++ b/src/test/unit/filesize.spec.jsx @@ -1,8 +1,8 @@ import React from 'react' import TestUtils from 'react-addons-test-utils' -import FineUploaderTraditional from 'src/wrappers/traditional' -import Filesize from 'src/components/filesize' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import Filesize from 'src/filesize' const sampleBlob = new Blob(['hi!'], { type : 'text/plain' }) const sampleBlobWrapper = { blob: sampleBlob, name: 'test' } diff --git a/src/test/unit/components/gallery.spec.jsx b/src/test/unit/gallery.spec.jsx similarity index 94% rename from src/test/unit/components/gallery.spec.jsx rename to src/test/unit/gallery.spec.jsx index 661d8f6..a4d2225 100644 --- a/src/test/unit/components/gallery.spec.jsx +++ b/src/test/unit/gallery.spec.jsx @@ -1,10 +1,10 @@ import React from 'react' import TestUtils from 'react-addons-test-utils' -import Dropzone from 'src/components/dropzone' -import FileInput from 'src/components/file-input' -import FineUploaderTraditional from 'src/wrappers/traditional' -import Gallery from 'src/components/gallery' +import Dropzone from 'src/dropzone' +import FileInput from 'src/file-input' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import Gallery from 'src/gallery' const isMobile = !!('ontouchstart' in window) const sampleBlob = new Blob(['hi!'], { type : 'text/plain' }) diff --git a/src/test/unit/components/pause-resume-button.spec.jsx b/src/test/unit/pause-resume-button.spec.jsx similarity index 95% rename from src/test/unit/components/pause-resume-button.spec.jsx rename to src/test/unit/pause-resume-button.spec.jsx index 4bfbe93..7560313 100644 --- a/src/test/unit/components/pause-resume-button.spec.jsx +++ b/src/test/unit/pause-resume-button.spec.jsx @@ -1,8 +1,8 @@ import React from 'react' import TestUtils from 'react-addons-test-utils' -import FineUploaderTraditional from 'src/wrappers/traditional' -import PauseResumeButton from 'src/components/pause-resume-button' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import PauseResumeButton from 'src/pause-resume-button' describe('', () => { let statusChangeCallback, uploadChunkCallback, uploader diff --git a/src/test/unit/components/progress-bar.spec.jsx b/src/test/unit/progress-bar.spec.jsx similarity index 98% rename from src/test/unit/components/progress-bar.spec.jsx rename to src/test/unit/progress-bar.spec.jsx index abfa779..a90425f 100644 --- a/src/test/unit/components/progress-bar.spec.jsx +++ b/src/test/unit/progress-bar.spec.jsx @@ -2,8 +2,8 @@ import qq from 'fine-uploader/lib/core/all' import React from 'react' import TestUtils from 'react-addons-test-utils' -import FineUploaderTraditional from 'src/wrappers/traditional' -import ProgressBar from 'src/components/progress-bar' +import FineUploaderTraditional from 'fine-uploader-wrappers' +import ProgressBar from 'src/progress-bar' describe('', () => { it('renders total progress bar when a file ID is not supplied & updates progress appropriately', () => { diff --git a/src/test/unit/components/retry-button.spec.jsx b/src/test/unit/retry-button.spec.jsx similarity index 96% rename from src/test/unit/components/retry-button.spec.jsx rename to src/test/unit/retry-button.spec.jsx index ae78ba8..853bf2b 100644 --- a/src/test/unit/components/retry-button.spec.jsx +++ b/src/test/unit/retry-button.spec.jsx @@ -1,8 +1,8 @@ import React from 'react' import TestUtils from 'react-addons-test-utils' -import RetryButton from 'src/components/retry-button' -import FineUploaderTraditional from 'src/wrappers/traditional' +import RetryButton from 'src/retry-button' +import FineUploaderTraditional from 'fine-uploader-wrappers' describe('', () => { const getButton = () => ( diff --git a/src/test/unit/components/status.spec.jsx b/src/test/unit/status.spec.jsx similarity index 94% rename from src/test/unit/components/status.spec.jsx rename to src/test/unit/status.spec.jsx index a00f6a9..6d33247 100644 --- a/src/test/unit/components/status.spec.jsx +++ b/src/test/unit/status.spec.jsx @@ -1,8 +1,8 @@ import React from 'react' import TestUtils from 'react-addons-test-utils' -import Status from 'src/components/status' -import FineUploaderTraditional from 'src/wrappers/traditional' +import Status from 'src/status' +import FineUploaderTraditional from 'fine-uploader-wrappers' describe('', () => { const getStatus = () => ( diff --git a/src/test/unit/components/thumbnail/index.spec.jsx b/src/test/unit/thumbnail/index.spec.jsx similarity index 99% rename from src/test/unit/components/thumbnail/index.spec.jsx rename to src/test/unit/thumbnail/index.spec.jsx index 197df61..440ae22 100644 --- a/src/test/unit/components/thumbnail/index.spec.jsx +++ b/src/test/unit/thumbnail/index.spec.jsx @@ -2,7 +2,7 @@ import qq from 'fine-uploader/lib/core/all' import React from 'react' import TestUtils from 'react-addons-test-utils' -import Thumbnail, { defaultMaxSize, notAvailableStatus, waitingStatus } from 'src/components/thumbnail' +import Thumbnail, { defaultMaxSize, notAvailableStatus, waitingStatus } from 'src/thumbnail' describe('', () => { let drawThumbnail, qqPromise, uploader diff --git a/src/test/unit/wrappers/base-wrapper.spec.js b/src/test/unit/wrappers/base-wrapper.spec.js deleted file mode 100644 index 064fa1c..0000000 --- a/src/test/unit/wrappers/base-wrapper.spec.js +++ /dev/null @@ -1,220 +0,0 @@ -import qq from 'fine-uploader/lib/core' - -import FineUploaderTraditional from 'src/wrappers/traditional' - -const sampleBlob = new Blob(['hi!'], { type : 'text/plain' }) -const sampleBlobWrapper = { blob: sampleBlob, name: 'test' } - -describe('Fine Uploader wrapper classes', () => { - describe('new instance consruction', () => { - it('provides access to its API', () => { - const wrapper = new FineUploaderTraditional({ - options: {} - }) - - expect(wrapper.methods).toBeTruthy() - expect(wrapper.methods.getFile).toBeTruthy() - expect(wrapper.methods.addFiles).toBeTruthy() - }) - - it('provides access to passed options', () => { - const wrapper = new FineUploaderTraditional({ - options: { - request: { - endpoint: 'foo/bar' - }, - callbacks: {} - } - }) - - expect(wrapper.options).toBeTruthy() - expect(wrapper.options).toEqual({ - request: { - endpoint: 'foo/bar' - } - }) - }) - - it('associates passed callbacks with underlying uploader instance', done => { - const wrapper = new FineUploaderTraditional({ - options: { - autoUpload: false, - callbacks: { - onSubmit: function(id, name) { - expect(id).toBe(0) - expect(name).toBe(sampleBlobWrapper.name) - - done() - } - } - } - }) - - wrapper.methods.addFiles(sampleBlobWrapper) - }) - }) - - describe('callback handling', () => { - it('associates multiple registered callback handlers w/ a single FU callback option && calls them in the order they were registered', done => { - let callbacksHit = 0 - - const wrapper = new FineUploaderTraditional({ - options: { - autoUpload: false, - callbacks: { - onSubmit: function(id, name) { - callbacksHit++ - expect(id).toBe(0) - expect(name).toBe(sampleBlobWrapper.name) - } - } - } - }) - - wrapper.on('submit', (id, name) => { - const records = wrapper.methods.getUploads() - expect(records.length).toBe(1) - expect(records[0].status).toBe(qq.status.SUBMITTING) - - expect(++callbacksHit).toBe(2) - expect(id).toBe(0) - expect(name).toBe(sampleBlobWrapper.name) - }) - - setTimeout(() => { - const records = wrapper.methods.getUploads() - expect(records[0].status).toBe(qq.status.SUBMITTED) - - done() - }, 100) - - wrapper.methods.addFiles(sampleBlobWrapper) - }) - - it('does not call subsequent registered non-thenable callbacks if an earlier callback indicates failure w/ `false`', done => { - let callbacksHit = 0 - - const wrapper = new FineUploaderTraditional({ - options: { - autoUpload: false, - callbacks: { - onSubmitted: function(id, name) { - callbacksHit++ - expect(id).toBe(0) - expect(name).toBe(sampleBlobWrapper.name) - return false - } - } - } - }) - - // this callback should never be executed - wrapper.on('submitted', () => { - callbacksHit++ - }) - - wrapper.methods.addFiles(sampleBlobWrapper) - - setTimeout(() => { - expect(callbacksHit).toBe(1) - - done() - }, 100) - }) - - it('does not call subsequent registered thenable callbacks if an earlier callback indicates failure w/ a Promise', done => { - let callbacksHit = 0 - - const wrapper = new FineUploaderTraditional({ - options: { - autoUpload: false, - callbacks: { - onSubmit: function(id, name) { - callbacksHit++ - expect(id).toBe(0) - expect(name).toBe(sampleBlobWrapper.name) - return false - } - } - } - }) - - // this callback should never be executed - wrapper.on('submit', () => { - callbacksHit++ - }) - - wrapper.methods.addFiles(sampleBlobWrapper) - - setTimeout(() => { - const records = wrapper.methods.getUploads() - expect(records.length).toBe(1) - expect(records[0].status).toBe(qq.status.REJECTED) - - expect(callbacksHit).toBe(1) - - done() - }, 100) - }) - - it('does not call subsequent registered thenable callbacks if an earlier callback indicates failure w/ `false`', done => { - let callbacksHit = 0 - - const wrapper = new FineUploaderTraditional({ - options: { - autoUpload: false, - callbacks: { - onSubmit: function(id, name) { - callbacksHit++ - expect(id).toBe(0) - expect(name).toBe(sampleBlobWrapper.name) - return Promise.reject() - } - } - } - }) - - // this callback should never be executed - wrapper.on('submit', () => { - callbacksHit++ - }) - - wrapper.methods.addFiles(sampleBlobWrapper) - - setTimeout(() => { - const records = wrapper.methods.getUploads() - expect(records.length).toBe(1) - expect(records[0].status).toBe(qq.status.REJECTED) - - expect(callbacksHit).toBe(1) - - done() - }, 100) - }) - - it('allows callback handlers to be removed', done => { - const handler = () => callbacksHit++ - let callbacksHit = 0 - - const wrapper = new FineUploaderTraditional({ - options: { autoUpload: false } - }) - - wrapper.on('submit', handler) - wrapper.methods.addFiles(sampleBlobWrapper) - - setTimeout(() => { - expect(callbacksHit).toBe(1) - - wrapper.off('submit', handler) - wrapper.methods.addFiles(sampleBlobWrapper) - - setTimeout(() => { - expect(callbacksHit).toBe(1) - - done() - }, 100) - }, 100) - }) - }) -}) diff --git a/src/components/thumbnail/index.jsx b/src/thumbnail/index.jsx similarity index 100% rename from src/components/thumbnail/index.jsx rename to src/thumbnail/index.jsx diff --git a/src/components/thumbnail/not-available-placeholder.jsx b/src/thumbnail/not-available-placeholder.jsx similarity index 100% rename from src/components/thumbnail/not-available-placeholder.jsx rename to src/thumbnail/not-available-placeholder.jsx diff --git a/src/components/thumbnail/placeholder.jsx b/src/thumbnail/placeholder.jsx similarity index 100% rename from src/components/thumbnail/placeholder.jsx rename to src/thumbnail/placeholder.jsx diff --git a/src/components/thumbnail/waiting-placeholder.jsx b/src/thumbnail/waiting-placeholder.jsx similarity index 100% rename from src/components/thumbnail/waiting-placeholder.jsx rename to src/thumbnail/waiting-placeholder.jsx diff --git a/src/wrappers/azure.js b/src/wrappers/azure.js deleted file mode 100644 index bf57212..0000000 --- a/src/wrappers/azure.js +++ /dev/null @@ -1,14 +0,0 @@ -import BaseWrapper from './base-wrapper' -import qq from 'fine-uploader/lib/core/azure' -import { traditional as callbackNames } from './callback-names' - -export default class FineUploaderAzure extends BaseWrapper { - constructor({ options }) { - super({ - callbackNames, - options, - qq, - type: 'azure' - }) - } -} diff --git a/src/wrappers/base-wrapper.js b/src/wrappers/base-wrapper.js deleted file mode 100644 index 870d3e6..0000000 --- a/src/wrappers/base-wrapper.js +++ /dev/null @@ -1,83 +0,0 @@ -import objectAssign from 'object-assign' - -import CallbackProxy from './callback-proxy' - -const callbackProxies = new WeakMap() - -export default class BaseWrapper { - constructor({ callbackNames, options, qq, type }) { - const callbacks = options.callbacks || {} - - const optionsSansCallbacks = objectAssign({}, options) - delete optionsSansCallbacks.callbacks - this.options = optionsSansCallbacks - - callbackProxies.set(this, createCallbackProxies(callbackNames)) - - registerOptionsCallbacks({ callbacks, callbackProxies: callbackProxies.get(this) }) - - this.methods = createFineUploader({ - callbackProxies: callbackProxies.get(this), - options: optionsSansCallbacks, - qq, - type - }) - } - - off(name, callback) { - const normalizedName = normalizeCallbackName(name) - const proxy = callbackProxies.get(this)[normalizedName] - - proxy.remove(callback) - } - - on(name, callback) { - const normalizedName = normalizeCallbackName(name) - const proxy = callbackProxies.get(this)[normalizedName] - - proxy.add(callback) - } -} - -const createCallbackProxies = names => { - const proxyMap = {} - - names.forEach(callbackName => { - proxyMap[callbackName] = new CallbackProxy(callbackName) - }) - - return proxyMap -} - -const createFineUploader = ({ callbackProxies, options, qq, type } ) => { - const optionsCopy = objectAssign({ callbacks: {} }, options) - - Object.keys(callbackProxies).forEach(callbackName => { - const proxy = callbackProxies[callbackName] - - optionsCopy.callbacks[callbackName] = proxy.proxyFunction - }) - - if (type === 'traditional') { - return new qq.FineUploaderBasic(optionsCopy) - } - else { - return new qq[type].FineUploaderBasic(optionsCopy) - } -} - -const normalizeCallbackName = name => { - if (!name.match(/^on[A-Z]/)) { - return `on${name[0].toUpperCase()}${name.slice(1)}` - } - - return name -} - -const registerOptionsCallbacks = ({ callbacks, callbackProxies }) => { - Object.keys(callbacks).forEach(callbackName => { - const callbackProxy = callbackProxies[callbackName] - - callbackProxy.add(callbacks[callbackName]) - }) -} diff --git a/src/wrappers/callback-names.js b/src/wrappers/callback-names.js deleted file mode 100644 index 351b12e..0000000 --- a/src/wrappers/callback-names.js +++ /dev/null @@ -1,39 +0,0 @@ -import objectAssign from 'object-assign' - -export const thenable = [ - 'onCancel', - 'onPasteReceived', - 'onSubmit', - 'onSubmitDelete', - 'onValidate', - 'onValidateBatch' -] - -export const traditional = [ - 'onAutoRetry', - 'onCancel', - 'onComplete', - 'onAllComplete', - 'onDelete', - 'onDeleteComplete', - 'onError', - 'onManualRetry', - 'onPasteReceived', - 'onProgress', - 'onResume', - 'onSessionRequestComplete', - 'onStatusChange', - 'onSubmit', - 'onSubmitDelete', - 'onSubmitted', - 'onTotalProgress', - 'onUpload', - 'onUploadChunk', - 'onUploadChunkSuccess', - 'onValidate', - 'onValidateBatch' -] - -export const s3 = objectAssign([], traditional, [ - 'onCredentialsExpired' -]) diff --git a/src/wrappers/callback-proxy.js b/src/wrappers/callback-proxy.js deleted file mode 100644 index 10fdc52..0000000 --- a/src/wrappers/callback-proxy.js +++ /dev/null @@ -1,106 +0,0 @@ -import objectAssign from 'object-assign' - -import { thenable as thenableCallbackNames } from './callback-names' - -const privateData = new WeakMap() -const callbacks = new WeakMap() - -export default class CallbackProxy { - constructor(name) { - callbacks.set(this, []) - - privateData.set(this, { - name, - proxyFunction: getProxyFunction.call(this, { name }) - }) - } - - add(callback) { - callbacks.get(this).push(callback) - } - - get name() { - return privateData.get(this).name - } - - get proxyFunction() { - return privateData.get(this).proxyFunction - } - - remove(callback) { - const index = callbacks.get(this).indexOf(callback) - if (index >= 0) { - callbacks.get(this).splice(index, 1) - } - } -} - -const getProxyFunction = function({ name }) { - const proxyClassContext = this - - return (...originalCallbackArguments) => { - const isThenable = thenableCallbackNames.indexOf(name) >= 0 - const registeredCallbacks = callbacks.get(proxyClassContext) - let callbackReturnValue - - if (isThenable) { - callbackReturnValue = executeThenableCallbacks({ registeredCallbacks, originalCallbackArguments }) - } - else { - objectAssign([], registeredCallbacks).every(callback => { - const returnValue = callback.apply(null, originalCallbackArguments) - - callbackReturnValue = returnValue - - return returnValue !== false - }) - } - - return callbackReturnValue - } -} - -const executeThenableCallbacks = ({ registeredCallbacks, originalCallbackArguments }) => { - if (registeredCallbacks.length) { - return executeThenableCallback({ - registeredCallbacks: objectAssign([], registeredCallbacks).reverse(), - originalCallbackArguments - }) - } - - return Promise.resolve() -} - -const executeThenableCallback = ({ registeredCallbacks, originalCallbackArguments} ) => { - return new Promise((resolve, reject) => { - const callback = registeredCallbacks.pop() - - let returnValue = callback.apply(null, originalCallbackArguments) - - if (returnValue && returnValue.then) { - returnValue - .then(result => { - if (registeredCallbacks.length) { - executeThenableCallback({ registeredCallbacks, originalCallbackArguments }) - .then(resolve, reject) - } - else { - resolve(result) - } - }) - .catch(error => reject(error)) - } - else if (returnValue === false) { - reject() - } - else { - if (registeredCallbacks.length) { - executeThenableCallback({ registeredCallbacks, originalCallbackArguments }) - .then(resolve, reject) - } - else { - resolve() - } - } - }) -} diff --git a/src/wrappers/s3.js b/src/wrappers/s3.js deleted file mode 100644 index 9222f30..0000000 --- a/src/wrappers/s3.js +++ /dev/null @@ -1,14 +0,0 @@ -import BaseWrapper from './base-wrapper' -import qq from 'fine-uploader/lib/core/s3' -import { s3 as callbackNames } from './callback-names' - -export default class FineUploaderS3 extends BaseWrapper { - constructor({ options }) { - super({ - callbackNames, - options, - qq, - type: 's3' - }) - } -} diff --git a/src/wrappers/traditional.js b/src/wrappers/traditional.js deleted file mode 100644 index acee598..0000000 --- a/src/wrappers/traditional.js +++ /dev/null @@ -1,14 +0,0 @@ -import BaseWrapper from './base-wrapper' -import qq from 'fine-uploader/lib/core' -import { traditional as callbackNames } from './callback-names' - -export default class FineUploaderTraditional extends BaseWrapper { - constructor({ options }) { - super({ - callbackNames, - options, - qq, - type: 'traditional' - }) - } -}