From 971e371a5c09feae3aabb81ab24a5d9938513eaa Mon Sep 17 00:00:00 2001 From: truztee Date: Mon, 20 Mar 2017 07:59:17 +0700 Subject: [PATCH] feat(Thumbnail + Gallery): Initial files thumbnail support (#77) * New `fromServer` property available on ``. * `` will attempt to render the `` for an initial file using the image URL associated with the corresponding initial file record. closes #51 --- README.md | 2 ++ package.json | 2 +- src/gallery/index.jsx | 35 ++++++++++++++++++-------- src/test/unit/gallery.spec.jsx | 14 +++++++++++ src/test/unit/thumbnail/index.spec.jsx | 16 ++++++++++-- src/thumbnail/index.jsx | 3 ++- 6 files changed, 57 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index f1809e0..3407c0d 100644 --- a/README.md +++ b/README.md @@ -829,6 +829,8 @@ The `` component allows you to easily render Fine Uploader generate - `waitingPlaceholder` - A custom element to display while waiting for the thumbnail. +- `fromServer` - Specify whether the current file was set from [initial file](https://docs.fineuploader.com/branch/master/features/session.html) + Suppose you wanted to render a thumbnail for each file as new files are submitted to Fine Uploader. Your React component may look like this: Note: This assumes you have additional components or code to allow files to actually be submitted to Fine Uploader. diff --git a/package.json b/package.json index ca27bb7..3170ac1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-fine-uploader", - "version": "0.5.0", + "version": "0.6.0", "license": "MIT", "description": "React UI components for using Fine Uploader in a React-based project.", "author": { diff --git a/src/gallery/index.jsx b/src/gallery/index.jsx index 952c7dc..3704eb5 100644 --- a/src/gallery/index.jsx +++ b/src/gallery/index.jsx @@ -53,9 +53,9 @@ class Gallery extends Component { } this._onStatusChange = (id, oldStatus, status) => { - if (status === 'submitted') { - const visibleFiles = this.state.visibleFiles + const visibleFiles = this.state.visibleFiles + if (status === 'submitted') { visibleFiles.push({ id }) this.setState({ visibleFiles }) } @@ -63,6 +63,12 @@ class Gallery extends Component { this._removeVisibleFile(id) } else if (status === 'upload successful' || status === 'upload failed') { + if (status === 'upload successful') { + const visibleFileIndex = this._findFileIndex(id) + if (visibleFileIndex < 0) { + visibleFiles.push({ id, fromServer: true }) + } + } this._updateVisibleFileStatus(id, status) } } @@ -116,7 +122,7 @@ class Gallery extends Component { transitionName='react-fine-uploader-gallery-files' > { - this.state.visibleFiles.map(({ id, status }) => ( + this.state.visibleFiles.map(({ id, status, fromServer }) => (
  • @@ -127,6 +133,7 @@ class Gallery extends Component { /> @@ -196,14 +203,7 @@ class Gallery extends Component { } _removeVisibleFile(id) { - let visibleFileIndex = -1 - - this.state.visibleFiles.some((file, index) => { - if (file.id === id) { - visibleFileIndex = index - return true - } - }) + const visibleFileIndex = this._findFileIndex(id) if (visibleFileIndex >= 0) { const visibleFiles = this.state.visibleFiles @@ -222,6 +222,19 @@ class Gallery extends Component { } }) } + + _findFileIndex(id) { + let visibleFileIndex = -1 + + this.state.visibleFiles.some((file, index) => { + if (file.id === id) { + visibleFileIndex = index + return true + } + }) + + return visibleFileIndex + } } const MaybeDropzone = ({ children, content, hasVisibleFiles, uploader, ...props }) => { diff --git a/src/test/unit/gallery.spec.jsx b/src/test/unit/gallery.spec.jsx index a4d2225..c63bd55 100644 --- a/src/test/unit/gallery.spec.jsx +++ b/src/test/unit/gallery.spec.jsx @@ -9,6 +9,7 @@ import Gallery from 'src/gallery' const isMobile = !!('ontouchstart' in window) const sampleBlob = new Blob(['hi!'], { type : 'text/plain' }) const sampleBlobWrapper = { blob: sampleBlob, name: 'test' } +const sampleCannedFile = { name: 'test', uuid: 'test uuid', thumbnailUrl: 'http://localhost/images/test.jpg' } describe('', () => { let uploader @@ -106,4 +107,17 @@ describe('', () => { }, 100) }, 100) }) + + it('renders a tile for each initial file', done => { + const GalleryComponent = TestUtils.renderIntoDocument() + + uploader.methods.addInitialFiles([sampleCannedFile]) + + setTimeout(() => { + const tiles = TestUtils.scryRenderedDOMComponentsWithClass(GalleryComponent, 'react-fine-uploader-gallery-file') + + expect(tiles.length).toBe(1) + done() + }, 100) + }) }) diff --git a/src/test/unit/thumbnail/index.spec.jsx b/src/test/unit/thumbnail/index.spec.jsx index 440ae22..13c18b6 100644 --- a/src/test/unit/thumbnail/index.spec.jsx +++ b/src/test/unit/thumbnail/index.spec.jsx @@ -26,7 +26,7 @@ describe('', () => { ) expect(ThumbnailComponent.refs.canvas.hasAttribute('hidden')).toBeFalsy() - expect(drawThumbnail).toHaveBeenCalledWith(3, ThumbnailComponent.refs.canvas, defaultMaxSize) + expect(drawThumbnail).toHaveBeenCalledWith(3, ThumbnailComponent.refs.canvas, defaultMaxSize, undefined) }) it('renders thumbnail as canvas using passed size', () => { @@ -38,7 +38,19 @@ describe('', () => { ) expect(ThumbnailComponent.refs.canvas.hasAttribute('hidden')).toBeFalsy() - expect(drawThumbnail).toHaveBeenCalledWith(3, ThumbnailComponent.refs.canvas, 333) + expect(drawThumbnail).toHaveBeenCalledWith(3, ThumbnailComponent.refs.canvas, 333, undefined) + }) + + it('renders thumbnail as canvas using passed thumbnail origin', () => { + qqPromise.success() + drawThumbnail.and.returnValue(qqPromise) + + const ThumbnailComponent = TestUtils.renderIntoDocument( + + ) + + expect(ThumbnailComponent.refs.canvas.hasAttribute('hidden')).toBeFalsy() + expect(drawThumbnail).toHaveBeenCalledWith(3, ThumbnailComponent.refs.canvas, 333, true) }) it('renders default waiting placeholder until thumbnail generation is complete', () => { diff --git a/src/thumbnail/index.jsx b/src/thumbnail/index.jsx index 2bc8e99..138985b 100644 --- a/src/thumbnail/index.jsx +++ b/src/thumbnail/index.jsx @@ -34,7 +34,8 @@ class Thumbnail extends Component { this.props.uploader.methods.drawThumbnail( this.props.id, this.refs.canvas, - this.props.maxSize + this.props.maxSize, + this.props.fromServer ) .then( () => {