From 4cb3a876d9bc9e3e9aa82060fee18bc026bfa91d Mon Sep 17 00:00:00 2001 From: Urse Daniel Date: Wed, 20 May 2020 13:57:17 +0300 Subject: [PATCH] [ACA-45] Drag and Drop a New Version (#5710) * added a new input: file * unit test - having singleFile option and a file as input, the type of the input for uploading should be button instead of file * added a click event for the upload button and also handle if having a file as input, the type of the input should be 'button' instead of 'file' * handling allowed for upload also for 'update' permissions over a dropped file. also emitting a new event for updating file version if i'm dropping a single file over another file. * unit tests for handling dropping a file over another * added a new input (file type) * passing a file to adf-version-upload component * new input as file and toggle new version if having that as input + unit test * added new input as file for new version * added new input to allow dropping a file over another to update it's version * added a new variable for handling dropping a file over another one and also handle a new event when we update the file version * pass a new dropped file to the dialog * new message * new method to allow isDropTarget for a file instead only to folders. * new emitter for updating a file's version * allows updating a file's version by dropping another file over it. * refactor allowDropFiles * update docs for drag&drop file into another file * update for drag&drop a file over another file functionality * made the allowDropFiles checking optional for isDropTarget property, only checking if the value is passed to the share-data-row Co-authored-by: Eugenio Romano --- demo-shell/resources/i18n/en.json | 2 +- .../app/components/files/files.component.html | 7 ++-- .../app/components/files/files.component.ts | 32 +++++++++++++++--- ...sion-manager-dialog-adapter.component.html | 2 +- ...ersion-manager-dialog-adapter.component.ts | 2 ++ .../components/document-list.component.md | 2 +- .../components/upload-button.component.md | 2 ++ .../components/upload-drag-area.component.md | 1 + .../upload-version-button.component.md | 2 ++ .../components/version-manager.component.md | 1 + docs/core/components/datatable.component.md | 1 - .../components/document-list.component.html | 1 - .../components/document-list.component.ts | 14 ++++---- .../data/share-data-row.model.ts | 18 ++++++++-- .../data/share-datatable-adapter.ts | 14 +++++--- .../components/base-upload/upload-base.ts | 4 +++ .../components/upload-button.component.html | 5 +-- .../upload-button.component.spec.ts | 13 ++++++++ .../components/upload-button.component.ts | 14 ++++++++ .../upload-drag-area.component.spec.ts | 33 +++++++++++++++++-- .../components/upload-drag-area.component.ts | 26 +++++++++------ .../version-manager.component.html | 1 + .../version-manager.component.spec.ts | 6 ++++ .../version-manager.component.ts | 23 +++++++++---- .../version-upload.component.html | 1 + .../version-upload.component.ts | 3 ++ .../datatable/datatable.component.html | 2 +- .../datatable/datatable.component.ts | 6 ---- 28 files changed, 185 insertions(+), 53 deletions(-) diff --git a/demo-shell/resources/i18n/en.json b/demo-shell/resources/i18n/en.json index 3b33c436f0..0f9aa6eeb7 100644 --- a/demo-shell/resources/i18n/en.json +++ b/demo-shell/resources/i18n/en.json @@ -119,7 +119,7 @@ "DOCUMENT_LIST": { "MULTISELECT_CHECKBOXES": "Multiselect (with checkboxes)", "THUMBNAILS": "Enable Thumbnails", - "ALLOW_DROP_FILES": "Enable Drop Files in a folder", + "ALLOW_DROP_FILES": "Enable Drop Files in a folder or a file", "MULTIPLE_FILE_UPLOAD": "Multiple File Upload", "FOLDER_UPLOAD": "Folder upload", "CUSTOM_FILTER": "Custom extensions filter", diff --git a/demo-shell/src/app/components/files/files.component.html b/demo-shell/src/app/components/files/files.component.html index 34611d4972..75f5654843 100644 --- a/demo-shell/src/app/components/files/files.component.html +++ b/demo-shell/src/app/components/files/files.component.html @@ -41,7 +41,8 @@ [versioning]="versioning" [adf-check-allowable-operation]="'create'" [adf-nodes]="disableDragArea ? getCurrentDocumentListNode() : []" - (beginUpload)="onBeginUpload($event)"> + (beginUpload)="onBeginUpload($event)" + (updateFileVersion)="onUploadNewVersion($event)">
diff --git a/lib/content-services/src/lib/upload/components/upload-button.component.spec.ts b/lib/content-services/src/lib/upload/components/upload-button.component.spec.ts index ca786c6d3d..a27a461e89 100644 --- a/lib/content-services/src/lib/upload/components/upload-button.component.spec.ts +++ b/lib/content-services/src/lib/upload/components/upload-button.component.spec.ts @@ -98,6 +98,19 @@ describe('UploadButtonComponent', () => { expect(compiled.querySelector('#uploadFolder')).toBeDefined(); }); + it('should have input type as button if receiving a file as input', () => { + component.multipleFiles = false; + component.file = new File([], 'Fake file name'); + const compiled = fixture.debugElement.nativeElement; + fixture.detectChanges(); + const inputButton = compiled.querySelector('#upload-single-file'); + expect(inputButton.type).toBe('button'); + + component.file = undefined; + fixture.detectChanges(); + expect(inputButton.type).toBe('file'); + }); + it('should disable uploadFolder button if disabled is true', () => { component.disabled = true; component.uploadFolders = true; diff --git a/lib/content-services/src/lib/upload/components/upload-button.component.ts b/lib/content-services/src/lib/upload/components/upload-button.component.ts index f31597e455..0ff8efcdf3 100644 --- a/lib/content-services/src/lib/upload/components/upload-button.component.ts +++ b/lib/content-services/src/lib/upload/components/upload-button.component.ts @@ -55,6 +55,10 @@ export class UploadButtonComponent extends UploadBase implements OnInit, OnChang @Input() tooltip: string = null; + /** Custom added file. The upload button type will be 'button' instead of 'file' */ + @Input() + file: File; + /** Emitted when create permission is missing. */ @Output() permissionEvent: EventEmitter = new EventEmitter(); @@ -100,6 +104,16 @@ export class UploadButtonComponent extends UploadBase implements OnInit, OnChang $event.target.value = ''; } + onClickUploadButton(): void { + const files: File[] = [this.file]; + + if (this.hasAllowableOperations) { + this.uploadFiles(files); + } else { + this.permissionEvent.emit(new PermissionModel({ type: 'content', action: 'upload', permission: 'create' })); + } + } + onDirectoryAdded($event: any): void { if (this.hasAllowableOperations) { const files: File[] = FileUtils.toFileArray($event.currentTarget.files); diff --git a/lib/content-services/src/lib/upload/components/upload-drag-area.component.spec.ts b/lib/content-services/src/lib/upload/components/upload-drag-area.component.spec.ts index ecd31ff1cf..d8c9bd7674 100644 --- a/lib/content-services/src/lib/upload/components/upload-drag-area.component.spec.ts +++ b/lib/content-services/src/lib/upload/components/upload-drag-area.component.spec.ts @@ -264,6 +264,34 @@ describe('UploadDragAreaComponent', () => { }); })); + it('should NOT upload the file if it is dropped on another file', () => { + const fakeItem = { + fullPath: '/folder-fake/file-fake.png', + isDirectory: false, + isFile: true, + name: 'file-fake.png', + relativeFolder: '/', + file: (callbackFile) => { + const fileFake = new File(['fakefake'], 'file-fake.png', { type: 'image/png' }); + callbackFile(fileFake); + } + }; + + addToQueueSpy.and.callFake((fileList) => { + expect(fileList.name).toBe('file'); + expect(fileList.options.path).toBe('pippo/'); + }); + + const fakeCustomEvent: CustomEvent = new CustomEvent('CustomEvent', { + detail: { + data: getFakeShareDataRow(), + files: [fakeItem] + } + }); + + component.onUploadFiles(fakeCustomEvent); + }); + it('should not upload a file if fileType is not in acceptedFilesType', async(() => { component.success = null; component.acceptedFilesType = '.pdf'; @@ -367,8 +395,8 @@ describe('UploadDragAreaComponent', () => { component.onUploadFiles(fakeCustomEvent); })); - it('should upload the file in the current folder when the target is file', async(() => { - + it('should trigger updating the file version when we drop a file over another file', async(() => { + spyOn(component.updateFileVersion, 'emit'); const fakeItem = { fullPath: '/folder-fake/file-fake.png', isDirectory: false, @@ -394,6 +422,7 @@ describe('UploadDragAreaComponent', () => { }); component.onUploadFiles(fakeCustomEvent); + expect(component.updateFileVersion.emit).toHaveBeenCalledWith(fakeCustomEvent); })); }); diff --git a/lib/content-services/src/lib/upload/components/upload-drag-area.component.ts b/lib/content-services/src/lib/upload/components/upload-drag-area.component.ts index a739ddaf28..65371c8150 100644 --- a/lib/content-services/src/lib/upload/components/upload-drag-area.component.ts +++ b/lib/content-services/src/lib/upload/components/upload-drag-area.component.ts @@ -26,9 +26,9 @@ import { UploadBase } from './base-upload/upload-base'; selector: 'adf-upload-drag-area', templateUrl: './upload-drag-area.component.html', styleUrls: ['./upload-drag-area.component.scss'], - host: { 'class': 'adf-upload-drag-area' }, + host: {'class': 'adf-upload-drag-area'}, viewProviders: [ - { provide: EXTENDIBLE_COMPONENT, useExisting: forwardRef(() => UploadDragAreaComponent) } + {provide: EXTENDIBLE_COMPONENT, useExisting: forwardRef(() => UploadDragAreaComponent)} ], encapsulation: ViewEncapsulation.None }) @@ -94,15 +94,21 @@ export class UploadDragAreaComponent extends UploadBase implements NodeAllowable onUploadFiles(event: CustomEvent) { event.stopPropagation(); event.preventDefault(); - const isAllowed: boolean = this.contentService.hasAllowableOperations(event.detail.data.obj.entry, AllowableOperationsEnum.CREATE); + const isAllowed: boolean = this.isTargetNodeFolder(event) ? + this.contentService.hasAllowableOperations(event.detail.data.obj.entry, AllowableOperationsEnum.CREATE) + : this.contentService.hasAllowableOperations(event.detail.data.obj.entry, AllowableOperationsEnum.UPDATE); if (isAllowed) { - const fileInfo: FileInfo[] = event.detail.files; - if (this.isTargetNodeFolder(event)) { - const destinationFolderName = event.detail.data.obj.entry.name; - fileInfo.map((file) => file.relativeFolder = destinationFolderName ? destinationFolderName.concat(file.relativeFolder) : file.relativeFolder); - } - if (fileInfo && fileInfo.length > 0) { - this.uploadFilesInfo(fileInfo); + if (!this.isTargetNodeFolder(event) && event.detail.files.length === 1) { + this.updateFileVersion.emit(event); + } else { + const fileInfo: FileInfo[] = event.detail.files; + if (this.isTargetNodeFolder(event)) { + const destinationFolderName = event.detail.data.obj.entry.name; + fileInfo.map((file) => file.relativeFolder = destinationFolderName ? destinationFolderName.concat(file.relativeFolder) : file.relativeFolder); + } + if (fileInfo && fileInfo.length > 0) { + this.uploadFilesInfo(fileInfo); + } } } } diff --git a/lib/content-services/src/lib/version-manager/version-manager.component.html b/lib/content-services/src/lib/version-manager/version-manager.component.html index a0c541430a..77fb0fe656 100644 --- a/lib/content-services/src/lib/version-manager/version-manager.component.html +++ b/lib/content-services/src/lib/version-manager/version-manager.component.html @@ -6,6 +6,7 @@ diff --git a/lib/content-services/src/lib/version-manager/version-manager.component.spec.ts b/lib/content-services/src/lib/version-manager/version-manager.component.spec.ts index 770969ee94..314efdfe35 100644 --- a/lib/content-services/src/lib/version-manager/version-manager.component.spec.ts +++ b/lib/content-services/src/lib/version-manager/version-manager.component.spec.ts @@ -74,6 +74,12 @@ describe('VersionManagerComponent', () => { expect(spyOnListVersionHistory).toHaveBeenCalledWith(node.id); }); + it('should toggle new version if given a new file as input', () => { + component.newFileVersion = new File([], 'New file version'); + fixture.detectChanges(); + expect(component.uploadState).toBe('open'); + }); + it('should display comments for versions when not configured otherwise', async(() => { fixture.detectChanges(); fixture.whenStable().then(() => { diff --git a/lib/content-services/src/lib/version-manager/version-manager.component.ts b/lib/content-services/src/lib/version-manager/version-manager.component.ts index 5dea538522..62e52ce7ed 100644 --- a/lib/content-services/src/lib/version-manager/version-manager.component.ts +++ b/lib/content-services/src/lib/version-manager/version-manager.component.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { Component, Input, ViewEncapsulation, ViewChild, Output, EventEmitter } from '@angular/core'; +import { Component, Input, ViewEncapsulation, ViewChild, Output, EventEmitter, OnInit } from '@angular/core'; import { Node } from '@alfresco/js-api'; import { VersionListComponent } from './version-list.component'; import { ContentService, AlfrescoApiService } from '@alfresco/adf-core'; @@ -27,26 +27,30 @@ import { trigger, state, style, animate, transition } from '@angular/animations' styleUrls: ['./version-manager.component.scss'], animations: [ trigger('uploadToggle', [ - state('open', style({ height: '175px', opacity: 1, visibility: 'visible' })), - state('close', style({ height: '0%', opacity: 0, visibility: 'hidden' })), + state('open', style({height: '175px', opacity: 1, visibility: 'visible'})), + state('close', style({height: '0%', opacity: 0, visibility: 'hidden'})), transition('open => close', [ - style({ visibility: 'hidden' }), + style({visibility: 'hidden'}), animate('0.4s cubic-bezier(0.25, 0.8, 0.25, 1)') ]), transition('close => open', [ - style({ visibility: 'visible' }), + style({visibility: 'visible'}), animate('0.4s cubic-bezier(0.25, 0.8, 0.25, 1)') ]) ]) ], encapsulation: ViewEncapsulation.None }) -export class VersionManagerComponent { +export class VersionManagerComponent implements OnInit { /** Target node to manage version history. */ @Input() node: Node; + /** New file for updating current version. */ + @Input() + newFileVersion: File; + /** Toggles showing/hiding of comments. */ @Input() showComments = true; @@ -72,6 +76,12 @@ export class VersionManagerComponent { private alfrescoApiService: AlfrescoApiService) { } + ngOnInit() { + if (this.newFileVersion) { + this.toggleNewVersion(); + } + } + refresh(node: Node) { this.alfrescoApiService.nodeUpdated.next(node); this.versionListComponent.loadVersionHistory(); @@ -80,6 +90,7 @@ export class VersionManagerComponent { } onUploadSuccess(event: any) { + this.newFileVersion = null; this.alfrescoApiService.nodeUpdated.next(event.value.entry); this.versionListComponent.loadVersionHistory(); this.uploadSuccess.emit(event.value.entry); diff --git a/lib/content-services/src/lib/version-manager/version-upload.component.html b/lib/content-services/src/lib/version-manager/version-upload.component.html index 76f17b4acb..7a648d1dc2 100644 --- a/lib/content-services/src/lib/version-manager/version-upload.component.html +++ b/lib/content-services/src/lib/version-manager/version-upload.component.html @@ -25,6 +25,7 @@ tooltip="{{ 'ADF_VERSION_LIST.ACTIONS.UPLOAD.TOOLTIP' | translate }}" [comment]="comment" [versioning]="true" + [file]="newFileVersion" [majorVersion]="isMajorVersion()" (success)="success.emit($event)" (error)="error.emit($event)"> diff --git a/lib/content-services/src/lib/version-manager/version-upload.component.ts b/lib/content-services/src/lib/version-manager/version-upload.component.ts index 8511f15ba6..96c2094fd2 100644 --- a/lib/content-services/src/lib/version-manager/version-upload.component.ts +++ b/lib/content-services/src/lib/version-manager/version-upload.component.ts @@ -35,6 +35,9 @@ export class VersionUploadComponent { @Input() node: Node; + @Input() + newFileVersion: File; + @Output() success = new EventEmitter(); diff --git a/lib/core/datatable/components/datatable/datatable.component.html b/lib/core/datatable/components/datatable/datatable.component.html index cb36eefa30..ef7ddee228 100644 --- a/lib/core/datatable/components/datatable/datatable.component.html +++ b/lib/core/datatable/components/datatable/datatable.component.html @@ -60,7 +60,7 @@ (select)="onEnterKeyPressed(row, $event)" (keyup)="onRowKeyUp(row, $event)" (keydown)="onRowEnterKeyDown(row, $event)" - [adf-upload]="allowDropFiles && rowAllowsDrop(row)" + [adf-upload]="rowAllowsDrop(row)" [adf-upload-data]="row" [ngStyle]="rowStyle" [ngClass]="getRowStyle(row)" diff --git a/lib/core/datatable/components/datatable/datatable.component.ts b/lib/core/datatable/components/datatable/datatable.component.ts index 236a48fc65..414248c3e2 100644 --- a/lib/core/datatable/components/datatable/datatable.component.ts +++ b/lib/core/datatable/components/datatable/datatable.component.ts @@ -105,12 +105,6 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, @Input() contextMenu: boolean = false; - /** Toggles file drop support for rows (see - * [Upload directive](upload.directive.md) for further details). - */ - @Input() - allowDropFiles: boolean = false; - /** The inline style to apply to every row. See * [NgStyle](https://angular.io/docs/ts/latest/api/common/index/NgStyle-directive.html) * docs for more details and usage examples.