ソースを参照

Feature: Added pending action when upload is in progress.

Oskar Wróbel 7 年 前
コミット
0b59c21a3b

+ 40 - 0
packages/ckeditor5-upload/src/filerepository.js

@@ -9,6 +9,7 @@
 
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
 
+import PendingActions from '@ckeditor/ckeditor5-core/src/pendingactions';
 import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
 import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
 import Collection from '@ckeditor/ckeditor5-utils/src/collection';
@@ -45,6 +46,13 @@ export default class FileRepository extends Plugin {
 	/**
 	 * @inheritDoc
 	 */
+	static get requires() {
+		return [ PendingActions ];
+	}
+
+	/**
+	 * @inheritDoc
+	 */
 	init() {
 		/**
 		 * Collection of loaders associated with this repository.
@@ -53,6 +61,19 @@ export default class FileRepository extends Plugin {
 		 */
 		this.loaders = new Collection();
 
+		// Keeps upload in a sync with pending actions.
+		this.loaders.on( 'add', () => this._updatePendingAction() );
+		this.loaders.on( 'remove', () => this._updatePendingAction() );
+
+		/**
+		 * Reference to a pending action registered in a {@link module:core/pendingactions~PendingActions} plugin
+		 * while upload is in progress. When there is no upload then value is `null`.
+		 *
+		 * @private
+		 * @type {Object} #_pendingAction
+		 */
+		this._pendingAction = null;
+
 		/**
 		 * A factory function which should be defined before using `FileRepository`.
 		 *
@@ -205,6 +226,25 @@ export default class FileRepository extends Plugin {
 
 		this.loaders.remove( loader );
 	}
+
+	/**
+	 * Registers or deregisters pending action bound with upload progress.
+	 *
+	 * @private
+	 */
+	_updatePendingAction() {
+		const pendingActions = this.editor.plugins.get( PendingActions );
+		const getMessage = value => `Upload in progress ${ value }%.`;
+
+		if ( this.loaders.length ) {
+			if ( !this._pendingAction ) {
+				this._pendingAction = pendingActions.add( getMessage( this.uploadedPercent ) );
+				this._pendingAction.bind( 'message' ).to( this, 'uploadedPercent', getMessage );
+			}
+		} else {
+			pendingActions.remove( this._pendingAction );
+		}
+	}
 }
 
 mix( FileRepository, ObservableMixin );

+ 64 - 0
packages/ckeditor5-upload/tests/filerepository.js

@@ -8,6 +8,7 @@
 import VirtualTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/virtualtesteditor';
 
 import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
+import PendingActions from '@ckeditor/ckeditor5-core/src/pendingactions';
 import FileRepository from '../src/filerepository';
 
 import Collection from '@ckeditor/ckeditor5-utils/src/collection';
@@ -91,6 +92,69 @@ describe( 'FileRepository', () => {
 		} );
 	} );
 
+	describe.only( 'pending actions', () => {
+		let pendingActions;
+
+		beforeEach( () => {
+			pendingActions = editor.plugins.get( PendingActions );
+		} );
+
+		it( 'should requires PendingActions plugin', () => {
+			expect( editor.plugins.get( PendingActions ) ).to.instanceof( PendingActions );
+		} );
+
+		it( 'should add pending action when upload is in progress', () => {
+			expect( pendingActions ).to.have.property( 'isPending', false );
+			expect( Array.from( pendingActions ) ).to.length( 0 );
+
+			fileRepository.createLoader( createNativeFileMock() );
+
+			expect( pendingActions ).to.have.property( 'isPending', true );
+			expect( Array.from( pendingActions, action => action.message ) ).to.have.members( [ 'Upload in progress 0%.' ] );
+		} );
+
+		it( 'should add only one pending action ai a case of multiple load', () => {
+			fileRepository.createLoader( createNativeFileMock() );
+			fileRepository.createLoader( createNativeFileMock() );
+			fileRepository.createLoader( createNativeFileMock() );
+
+			expect( Array.from( pendingActions ) ).to.length( 1 );
+		} );
+
+		it( 'should remove pending action when all uploads are finished', () => {
+			expect( pendingActions ).to.have.property( 'isPending', false );
+			expect( Array.from( pendingActions ) ).to.length( 0 );
+
+			const loader1 = fileRepository.createLoader( createNativeFileMock() );
+			const loader2 = fileRepository.createLoader( createNativeFileMock() );
+
+			expect( pendingActions ).to.have.property( 'isPending', true );
+			expect( Array.from( pendingActions, action => action.message ) ).to.have.members( [ 'Upload in progress 0%.' ] );
+
+			fileRepository.destroyLoader( loader1 );
+
+			expect( pendingActions ).to.have.property( 'isPending', true );
+			expect( Array.from( pendingActions, action => action.message ) ).to.have.members( [ 'Upload in progress 0%.' ] );
+
+			fileRepository.destroyLoader( loader2 );
+
+			expect( pendingActions ).to.have.property( 'isPending', false );
+			expect( Array.from( pendingActions ) ).to.length( 0 );
+		} );
+
+		it( 'should bind pending action message to upload percentage value', () => {
+			fileRepository.createLoader( createNativeFileMock() );
+
+			fileRepository.uploadedPercent = 10;
+
+			expect( Array.from( pendingActions )[ 0 ] ).to.have.property( 'message', 'Upload in progress 10%.' );
+
+			fileRepository.uploadedPercent = 30;
+
+			expect( Array.from( pendingActions )[ 0 ] ).to.have.property( 'message', 'Upload in progress 30%.' );
+		} );
+	} );
+
 	describe( 'createLoader()', () => {
 		it( 'should return null if adapter is not present', () => {
 			const stub = testUtils.sinon.stub( log, 'error' );