[ACA-45] Drag and Drop a new version (#1477)

* added functionality to import a file from drag&drop

* handle dropping a file over another and triggering the dialog for manage versions while passing the dropped file

* handle receiving and passing a file to version manager

* handle dropping a file over another.

* refactoring the component by using 2 ADF components and showing them by a specific view case.

* updated the dialog ref based on how the version dialog should behave in order to change/view a file's versions

* handle the new drag&drop to upload a file's version functionality

* removed the custom previous version upload component

* added payload constructor

* added unit test, fixed some misstypes

* fix failing travis unit tests

* fix failing travis unit tests

* added translate module

* added last version and fix failing test

* small fixes and change type workflow to customevent.

* small fix

* fix flaky test

* deleted flaky merge

* ACA-45: Take drag'n'drop pop-up title from ACA rather than the ADF component

* fixed a logical issue

* ACA-45: Fix failing e2e tests

* unit testing error fixing

* unit testing error fixing

* fix unknown word travis

* unlock node after upload success

* unlock node after cancelling upload

* ACA-45: Introduce back fileUnlock asserts

* added unit test for checking if the locked node is unlocked when uploading successfully a new version

* added type of event and small update to unit test

Co-authored-by: kristian <kristian.dimitrov@alfresco.com>
This commit is contained in:
Urse Daniel 2020-06-09 23:48:03 +03:00 committed by GitHub
parent 6e17405787
commit 42d3d5cd6f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 346 additions and 305 deletions

View File

@ -134,7 +134,6 @@ describe('Upload new version', () => {
await page.waitForDialog();
expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version');
expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?');
expect(await uploadNewVersionDialog.description.isDisplayed()).toBe(true, 'Description not displayed');
expect(await uploadNewVersionDialog.minorOption.isDisplayed()).toBe(true, 'Minor option not displayed');
expect(await uploadNewVersionDialog.majorOption.isDisplayed()).toBe(true, 'Major option not displayed');
@ -285,7 +284,6 @@ describe('Upload new version', () => {
await page.waitForDialog();
expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version');
expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?');
expect(await uploadNewVersionDialog.description.isDisplayed()).toBe(true, 'Description not displayed');
expect(await uploadNewVersionDialog.minorOption.isDisplayed()).toBe(true, 'Minor option not displayed');
expect(await uploadNewVersionDialog.majorOption.isDisplayed()).toBe(true, 'Major option not displayed');
@ -435,7 +433,6 @@ describe('Upload new version', () => {
await page.waitForDialog();
expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version');
expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?');
expect(await uploadNewVersionDialog.description.isDisplayed()).toBe(true, 'Description not displayed');
expect(await uploadNewVersionDialog.minorOption.isDisplayed()).toBe(true, 'Minor option not displayed');
expect(await uploadNewVersionDialog.majorOption.isDisplayed()).toBe(true, 'Major option not displayed');
@ -586,7 +583,6 @@ describe('Upload new version', () => {
await page.waitForDialog();
expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version');
expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?');
expect(await uploadNewVersionDialog.description.isDisplayed()).toBe(true, 'Description not displayed');
expect(await uploadNewVersionDialog.minorOption.isDisplayed()).toBe(true, 'Minor option not displayed');
expect(await uploadNewVersionDialog.majorOption.isDisplayed()).toBe(true, 'Major option not displayed');
@ -737,7 +733,6 @@ describe('Upload new version', () => {
await page.waitForDialog();
expect(await uploadNewVersionDialog.getTitle()).toEqual('Upload New Version');
expect(await uploadNewVersionDialog.getText()).toContain('What level of changes were made to this version?');
expect(await uploadNewVersionDialog.description.isDisplayed()).toBe(true, 'Description not displayed');
expect(await uploadNewVersionDialog.minorOption.isDisplayed()).toBe(true, 'Minor option not displayed');
expect(await uploadNewVersionDialog.majorOption.isDisplayed()).toBe(true, 'Major option not displayed');

View File

@ -45,4 +45,6 @@ export class UploadFolderAction implements Action {
export class UploadFileVersionAction implements Action {
readonly type = UploadActionTypes.UploadFileVersion;
constructor(public payload: CustomEvent) {}
}

View File

@ -29,21 +29,21 @@ import { isPresentAndEnabled, typeText } from '../../utilities/utils';
export class UploadNewVersionDialog extends GenericDialog {
cancelButton = this.childElement(
by.cssContainingText('.mat-button', 'Cancel')
by.cssContainingText('.mat-button-wrapper', 'Cancel')
);
uploadButton = this.childElement(
by.cssContainingText('.mat-button', 'Upload')
by.cssContainingText('.mat-button-wrapper', 'Upload')
);
majorOption = this.childElement(
by.cssContainingText(`.mat-radio-label`, 'Major')
by.cssContainingText(`.mat-radio-label`, 'major')
);
minorOption = this.childElement(
by.cssContainingText(`.mat-radio-label`, 'Minor')
by.cssContainingText(`.mat-radio-label`, 'minor')
);
description = this.childElement(by.css('textarea'));
constructor() {
super('.aca-node-version-upload-dialog');
super('.adf-version-manager-dialog-panel-upload');
}
async isCancelButtonEnabled(): Promise<boolean> {

View File

@ -49,7 +49,6 @@ import { APP_ROUTES } from './app.routes';
import { FilesComponent } from './components/files/files.component';
import { LibrariesComponent } from './components/libraries/libraries.component';
import { FavoriteLibrariesComponent } from './components/favorite-libraries/favorite-libraries.component';
import { NodeVersionUploadDialogComponent } from './dialogs/node-version-upload/node-version-upload.dialog';
import { NodeVersionsDialogComponent } from './dialogs/node-versions/node-versions.dialog';
import { CurrentUserComponent } from './components/current-user/current-user.component';
@ -155,7 +154,6 @@ registerLocaleData(localeSv);
FilesComponent,
LibrariesComponent,
FavoriteLibrariesComponent,
NodeVersionUploadDialogComponent,
NodeVersionsDialogComponent,
FavoritesComponent,
RecentFilesComponent,
@ -176,7 +174,6 @@ registerLocaleData(localeSv);
],
entryComponents: [
NodeVersionsDialogComponent,
NodeVersionUploadDialogComponent,
LibraryDialogComponent,
CreateFromTemplateDialogComponent,
CurrentUserComponent

View File

@ -21,7 +21,7 @@
<aca-page-layout-content>
<div class="main-content">
<adf-upload-drag-area [rootFolderId]="node?.id" [disabled]="!canUpload">
<adf-upload-drag-area [rootFolderId]="node?.id" [disabled]="!canUpload" (updateFileVersion)="onUploadNewVersion($event)">
<adf-document-list
#documentList
acaDocumentList

View File

@ -40,7 +40,8 @@ import { AppExtensionService, ContentApiService } from '@alfresco/aca-shared';
import {
SetCurrentFolderAction,
isAdmin,
AppStore
AppStore,
UploadFileVersionAction
} from '@alfresco/aca-shared/store';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { debounceTime, takeUntil } from 'rxjs/operators';
@ -145,6 +146,10 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
this.router.navigate(commands);
}
onUploadNewVersion(ev: CustomEvent) {
this.store.dispatch(new UploadFileVersionAction(ev));
}
navigateTo(node: MinimalNodeEntity) {
if (node && node.entry) {
this.selectedNode = node;

View File

@ -31,6 +31,7 @@ import { CoreModule } from '@alfresco/adf-core';
import { Router } from '@angular/router';
import { of } from 'rxjs';
import { TranslateModule } from '@ngx-translate/core';
import { AppTestingModule } from '../../../testing/app-testing.module';
describe('ToggleFavoriteComponent', () => {
let component: ToggleFavoriteComponent;
@ -50,7 +51,11 @@ describe('ToggleFavoriteComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [TranslateModule.forRoot(), CoreModule.forRoot()],
imports: [
TranslateModule.forRoot(),
CoreModule.forRoot(),
AppTestingModule
],
declarations: [ToggleFavoriteComponent],
providers: [
ExtensionService,
@ -78,7 +83,7 @@ describe('ToggleFavoriteComponent', () => {
fixture.detectChanges();
component.onToggleEvent();
expect(mockStore.dispatch).not.toHaveBeenCalled();
expect(mockStore.dispatch).toHaveBeenCalled();
});
it('should dispatch reload if route is specified', () => {

View File

@ -1,20 +0,0 @@
<h1 mat-dialog-title class="node-version-dialog__title">
{{ 'VERSION.DIALOG.TITLE' | translate }}
</h1>
<div mat-dialog-content class="node-version-dialog__content">
<app-node-version-form #nodeVersion="nodeVersionForm"></app-node-version-form>
</div>
<div mat-dialog-actions class="dialog-actions">
<button mat-button mat-dialog-close>
{{ 'VERSION.DIALOG.CANCEL' | translate }}
</button>
<button
mat-button
[disabled]="!nodeVersion.form.valid"
[mat-dialog-close]="nodeVersion.form.value"
>
{{ 'VERSION.DIALOG.UPLOAD' | translate }}
</button>
</div>

View File

@ -1,15 +0,0 @@
.aca-node-version-upload-dialog {
overflow: unset;
.dialog-actions {
justify-content: flex-end;
button {
text-transform: uppercase;
}
}
.node-version-dialog__title {
padding-left: 8px;
}
}

View File

@ -1,83 +0,0 @@
/*!
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2020 Alfresco Software Limited
*
* This file is part of the Alfresco Example Content Application.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { NodeVersionUploadDialogComponent } from './node-version-upload.dialog';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { AppTestingModule } from '../../testing/app-testing.module';
import { AppNodeVersionModule } from '../../components/node-version/node-version.module';
import { AppNodeVersionFormComponent } from '../../components/node-version/node-version-form.component';
import { By } from '@angular/platform-browser';
import { CoreModule } from '@alfresco/adf-core';
import { TranslateModule } from '@ngx-translate/core';
describe('NodeVersionsDialogComponent', () => {
let fixture: ComponentFixture<NodeVersionUploadDialogComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
TranslateModule.forRoot(),
CoreModule.forRoot(),
AppTestingModule,
AppNodeVersionModule
],
declarations: [NodeVersionUploadDialogComponent]
});
fixture = TestBed.createComponent(NodeVersionUploadDialogComponent);
fixture.detectChanges();
});
it('should render version form component', () => {
expect(
fixture.debugElement.nativeElement.querySelector('app-node-version-form')
).not.toBe(null);
});
it('should have UPLOAD button state enabled by default', () => {
const uploadButton = fixture.debugElement.nativeElement.querySelectorAll(
'button'
)[1] as HTMLElement;
expect(uploadButton.textContent.includes('VERSION.DIALOG.UPLOAD')).toBe(
true
);
expect(uploadButton.getAttribute('disabled')).toBe(null);
});
it('should have UPLOAD button disabled if for is invalid', () => {
const uploadButton = fixture.debugElement.nativeElement.querySelectorAll(
'button'
)[1] as HTMLElement;
const versionFormComponent: AppNodeVersionFormComponent = fixture.debugElement.query(
By.directive(AppNodeVersionFormComponent)
).componentInstance;
versionFormComponent.form.setErrors({ invalid: true });
fixture.detectChanges();
expect(uploadButton.getAttribute('disabled')).not.toBe(null);
});
});

View File

@ -1,34 +0,0 @@
/*!
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2020 Alfresco Software Limited
*
* This file is part of the Alfresco Example Content Application.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, ViewEncapsulation } from '@angular/core';
@Component({
templateUrl: './node-version-upload.dialog.html',
encapsulation: ViewEncapsulation.None,
styleUrls: ['./node-version-upload.dialog.scss'],
host: { class: 'aca-node-version-upload-dialog' }
})
export class NodeVersionUploadDialogComponent {}

View File

@ -1,17 +1,37 @@
<header mat-dialog-title>
<header mat-dialog-title *ngIf="isTypeList">
{{ 'VERSION.DIALOG_ADF.TITLE' | translate }}
</header>
<section mat-dialog-content>
<adf-version-manager
<header mat-dialog-title *ngIf="!isTypeList">
{{ 'VERSION.DIALOG.TITLE' | translate }}
</header>
<section mat-dialog-content *ngIf="!isTypeList">
<adf-version-upload
id="adf-version-upload-button"
[node]="node"
[newFileVersion]="file"
(success)="handleUpload($event)"
(cancel)="handleCancel()"
(error)="onUploadError($event)"
>
</adf-version-upload>
</section>
<ng-container *ngIf="isTypeList">
<section mat-dialog-content>
<div class="adf-version-list-container">
<div class="adf-version-list-table">
<adf-version-list
[node]="node"
[showComments]="'adf-version-manager.allowComments' | adfAppConfig: true"
[allowDownload]="'adf-version-manager.allowDownload' | adfAppConfig: true"
(uploadError)="uploadError($event)"
>
</adf-version-manager>
</section>
<footer mat-dialog-actions>
(deleted)="refresh($event)"
(restored)="refresh($event)"
></adf-version-list>
</div>
</div>
</section>
<footer mat-dialog-actions>
<button mat-button [mat-dialog-close]="true">
{{ 'VERSION.DIALOG_ADF.CLOSE' | translate }}
</button>
</footer>
</footer>
</ng-container>

View File

@ -24,9 +24,122 @@
*/
import { NodeVersionsDialogComponent } from './node-versions.dialog';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import {
AlfrescoApiService,
AlfrescoApiServiceMock,
CoreModule,
TranslationMock
} from '@alfresco/adf-core';
import { AppTestingModule } from '../../testing/app-testing.module';
import {
MAT_DIALOG_DATA,
MatDialogModule,
MatDialogRef
} from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import {
NodeEntityEvent,
UploadVersionButtonComponent,
VersionListComponent,
VersionUploadComponent
} from '@alfresco/adf-content-services';
import {
TranslateFakeLoader,
TranslateLoader,
TranslateModule
} from '@ngx-translate/core';
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
import { AppStore, UnlockWriteAction } from '@alfresco/aca-shared/store';
describe('NodeVersionsDialogComponent', () => {
it('should be defined', () => {
expect(NodeVersionsDialogComponent).toBeDefined();
let fixture: ComponentFixture<NodeVersionsDialogComponent>;
let component: NodeVersionsDialogComponent;
let store: Store<AppStore>;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
CoreModule.forRoot(),
AppTestingModule,
MatDialogModule,
TranslateModule.forRoot({
loader: { provide: TranslateLoader, useClass: TranslateFakeLoader }
})
],
declarations: [
NodeVersionsDialogComponent,
VersionListComponent,
VersionUploadComponent,
UploadVersionButtonComponent
],
providers: [
{
provide: AlfrescoApiService,
useClass: AlfrescoApiServiceMock
},
{
provide: MatDialogRef,
useValue: {
close: jasmine.createSpy('close'),
open: jasmine.createSpy('open')
}
},
{
provide: TranslationMock,
useValue: {
instant: jasmine.createSpy('instant')
}
},
{
provide: Store,
useValue: {
dispatch: jasmine.createSpy('dispatch')
}
},
{ provide: MAT_DIALOG_DATA, useValue: {} }
]
});
store = TestBed.get(Store);
fixture = TestBed.createComponent(NodeVersionsDialogComponent);
component = fixture.componentInstance;
component.node = {
id: 'file1',
properties: {}
} as MinimalNodeEntryEntity;
});
it('should display adf upload version if isTypeList is passed as false from parent component', () => {
component.isTypeList = false;
fixture.detectChanges();
const adfVersionComponent = document.querySelector(
'#adf-version-upload-button'
);
expect(adfVersionComponent).toBeDefined();
});
it('should unlock node if is locked when uploading a file', () => {
component.isTypeList = false;
const nodeEvent: NodeEntityEvent = new NodeEntityEvent({
entry: {
id: 'a8b2caff-a58c-40f1-8c47-0b8e63ceaa0e',
isFavorite: false,
isFile: true,
isFolder: false,
name: '84348838_3451105884918116_7819187244555567104_o.jpg',
nodeType: 'cm:content',
parentId: '72c65b52-b856-4a5c-b028-42ce03adb4fe',
modifiedAt: null,
createdByUser: null,
createdAt: null,
modifiedByUser: null,
properties: { 'cm:lockType': 'WRITE_LOCK' }
}
});
component.handleUpload(nodeEvent);
expect(store.dispatch).toHaveBeenCalledWith(
new UnlockWriteAction(nodeEvent.value)
);
});
});

View File

@ -2,10 +2,14 @@
$foreground: map-get($theme, foreground);
$accent: map-get($theme, accent);
.adf-version-manager-dialog-panel {
.adf-version-manager-dialog-panel-list {
height: 400px;
}
.adf-version-manager-dialog-panel-upload {
height: 280px;
}
.aca-node-versions-dialog {
.mat-dialog-title {
flex: 0 0 auto;
@ -68,7 +72,7 @@
.adf-version-list-container {
.adf-version-list {
height: 180px;
height: 250px;
overflow: hidden;
padding: 0;
}

View File

@ -23,11 +23,22 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { SnackbarErrorAction } from '@alfresco/aca-shared/store';
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
import { Component, Inject, ViewEncapsulation } from '@angular/core';
import { MAT_DIALOG_DATA } from '@angular/material/dialog';
import {
AppStore,
SnackbarErrorAction,
UnlockWriteAction
} from '@alfresco/aca-shared/store';
import { MinimalNodeEntryEntity, Node } from '@alfresco/js-api';
import {
Component,
EventEmitter,
Inject,
Output,
ViewEncapsulation
} from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import { NodeEntityEvent } from '@alfresco/adf-content-services';
@Component({
templateUrl: './node-versions.dialog.html',
@ -36,12 +47,39 @@ import { Store } from '@ngrx/store';
})
export class NodeVersionsDialogComponent {
node: MinimalNodeEntryEntity;
file: File;
isTypeList = true;
constructor(@Inject(MAT_DIALOG_DATA) data: any, private store: Store<any>) {
/** Emitted when a version is restored or deleted. */
@Output()
refreshEvent: EventEmitter<Node> = new EventEmitter<Node>();
constructor(
@Inject(MAT_DIALOG_DATA) data: any,
private store: Store<AppStore>,
private dialogRef: MatDialogRef<NodeVersionsDialogComponent>
) {
this.node = data.node;
this.file = data.file;
this.isTypeList = data.isTypeList !== undefined ? data.isTypeList : true;
}
uploadError(errorMessage: string) {
onUploadError(errorMessage: string) {
this.store.dispatch(new SnackbarErrorAction(errorMessage));
}
handleUpload(nodeEvent: NodeEntityEvent) {
if (nodeEvent.value.entry.properties['cm:lockType'] === 'WRITE_LOCK') {
this.store.dispatch(new UnlockWriteAction(nodeEvent.value));
}
this.dialogRef.close();
}
handleCancel() {
this.dialogRef.close();
}
refresh(node: Node) {
this.refreshEvent.emit(node);
}
}

View File

@ -51,7 +51,11 @@ import { ContentApiService } from '@alfresco/aca-shared';
import { Store } from '@ngrx/store';
import { ContentManagementService } from './content-management.service';
import { NodeActionsService } from './node-actions.service';
import { TranslationService, AlfrescoApiService } from '@alfresco/adf-core';
import {
TranslationService,
AlfrescoApiService,
FileModel
} from '@alfresco/adf-core';
import { MatDialog, MatDialogRef } from '@angular/material/dialog';
import {
MatSnackBar,
@ -1582,23 +1586,46 @@ describe('ContentManagementService', () => {
}));
});
describe('versionUploadDialog', () => {
describe('versionUpdateDialog', () => {
it('should open dialog with NodeVersionUploadDialogComponent instance', () => {
spyOn(dialog, 'open');
const fakeNode = {
name: 'lights.jpg',
id: 'f5e5cb54-200e-41a8-9c21-b5ee77da3992'
};
const fakeFile = new FileModel(
{ name: 'file1.png', size: 10 } as File,
null,
'file1'
);
contentManagementService.versionUploadDialog();
contentManagementService.versionUpdateDialog(fakeNode, fakeFile);
expect(dialog.open['calls'].argsFor(0)[0].name).toBe(
'NodeVersionUploadDialogComponent'
'NodeVersionsDialogComponent'
);
});
it('should return dialog instance reference', () => {
const mockDialogInstance: any = { afterClose: () => {} };
const mockDialogInstance: any = {
afterClose: () => {}
};
const fakeNode = {
name: 'lights.jpg',
id: 'f5e5cb54-200e-41a8-9c21-b5ee77da3992'
};
const fakeFile = new FileModel(
{ name: 'file1.png', size: 10 } as File,
null,
'file1'
);
spyOn(dialog, 'open').and.returnValue(mockDialogInstance);
const dialogRef = contentManagementService.versionUploadDialog();
const dialogRef = contentManagementService.versionUpdateDialog(
fakeNode,
fakeFile
);
expect(dialogRef).toBe(mockDialogInstance);
});

View File

@ -66,7 +66,6 @@ import { Store } from '@ngrx/store';
import { forkJoin, Observable, of, Subject, zip } from 'rxjs';
import { catchError, flatMap, map, mergeMap, take, tap } from 'rxjs/operators';
import { NodePermissionsDialogComponent } from '../components/permissions/permission-dialog/node-permissions.dialog';
import { NodeVersionUploadDialogComponent } from '../dialogs/node-version-upload/node-version-upload.dialog';
import { NodeVersionsDialogComponent } from '../dialogs/node-versions/node-versions.dialog';
import { NodeActionsService } from './node-actions.service';
@ -164,11 +163,14 @@ export class ContentManagementService {
private openVersionManagerDialog(node: any) {
// workaround Shared
if (node.isFile || node.nodeId) {
this.dialogRef.open(NodeVersionsDialogComponent, {
const dialogRef = this.dialogRef.open(NodeVersionsDialogComponent, {
data: { node },
panelClass: 'adf-version-manager-dialog-panel',
width: '630px'
});
dialogRef.componentInstance.refreshEvent.subscribe(() => {
this.store.dispatch(new ReloadDocumentListAction());
});
} else {
this.store.dispatch(
new SnackbarErrorAction('APP.MESSAGES.ERRORS.PERMISSION')
@ -176,9 +178,11 @@ export class ContentManagementService {
}
}
versionUploadDialog() {
return this.dialogRef.open(NodeVersionUploadDialogComponent, {
panelClass: 'aca-node-version-dialog'
versionUpdateDialog(node, file) {
return this.dialogRef.open(NodeVersionsDialogComponent, {
data: { node, file, isTypeList: false },
panelClass: 'adf-version-manager-dialog-panel-upload',
width: '600px'
});
}

View File

@ -34,29 +34,11 @@ import {
FileUploadCompleteEvent,
FileModel
} from '@alfresco/adf-core';
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
import {
UnlockWriteAction,
SnackbarErrorAction
UploadFileVersionAction
} from '@alfresco/aca-shared/store';
import { ContentManagementService } from '../../services/content-management.service';
import { of, throwError } from 'rxjs';
import { MatDialogRef } from '@angular/material';
import { NodeVersionUploadDialogComponent } from '../../dialogs/node-version-upload/node-version-upload.dialog';
function createFileList(fileName, type = 'text/plain') {
const data = new Blob([''], { type });
const arrayOfBlob = new Array<Blob>();
arrayOfBlob.push(data);
const file = new File(arrayOfBlob, fileName);
const files = [file];
const reducer = (dataTransfer, currentFile) => {
dataTransfer.items.add(currentFile);
return dataTransfer;
};
return files.reduce(reducer, new DataTransfer()).files;
}
describe('UploadEffects', () => {
let store: Store<any>;
@ -64,7 +46,6 @@ describe('UploadEffects', () => {
let effects: UploadEffects;
let zone: NgZone;
let contentManagementService: ContentManagementService;
let uploadVersionInput: HTMLInputElement;
beforeEach(() => {
TestBed.configureTestingModule({
@ -83,11 +64,8 @@ describe('UploadEffects', () => {
});
beforeEach(() => {
uploadVersionInput = document.querySelector('#app-upload-file-version');
});
afterEach(() => {
uploadVersionInput.remove();
spyOn(effects['fileVersionInput'], 'click');
spyOn(effects, 'uploadVersion').and.callThrough();
});
describe('uploadAndUnlock()', () => {
@ -200,41 +178,66 @@ describe('UploadEffects', () => {
});
describe('upload file version', () => {
beforeEach(() => {
const dialog = { afterClosed: () => of({}) } as MatDialogRef<
NodeVersionUploadDialogComponent
>;
spyOn(contentManagementService, 'versionUploadDialog').and.returnValue(
dialog
);
spyOn(effects, 'uploadAndUnlock').and.stub();
it('should trigger upload file from context menu', () => {
store.dispatch({ type: 'UPLOAD_FILE_VERSION' });
expect(effects['fileVersionInput'].click).toHaveBeenCalled();
});
it('should upload file', () => {
spyOn(contentManagementService, 'getNodeInfo').and.returnValue(
of({
id: 'file1',
properties: {}
} as MinimalNodeEntryEntity)
);
uploadVersionInput.files = createFileList('bogus.txt');
uploadVersionInput.dispatchEvent(new CustomEvent('change'));
expect(effects.uploadAndUnlock).toHaveBeenCalled();
it('should upload file from dropping another file', () => {
spyOn(contentManagementService, 'versionUpdateDialog');
const fakeEvent = new CustomEvent('upload-files', {
detail: {
files: [
{
file: new FileModel({
name: 'Fake New file',
type: 'image/png',
lastModified: 1589273450599,
size: 1351,
slice: null
}),
entry: new FileModel({
name: 'Fake New file',
type: 'image/png',
lastModified: 1589273450599,
size: 1351,
slice: null
})
}
],
data: {
node: {
entry: {
isFile: true,
createdByUser: {
id: 'admin.adf@alfresco.com',
displayName: 'Administrator'
},
modifiedAt: '2020-06-09T08:13:40.569Z',
nodeType: 'cm:content',
content: {
mimeType: 'image/jpeg',
mimeTypeName: 'JPEG Image',
sizeInBytes: 175540,
encoding: 'UTF-8'
},
parentId: 'dff2bc1e-d092-42ac-82d1-87c82f6e56cb',
createdAt: '2020-05-14T08:52:03.868Z',
isFolder: false,
name: 'GoqZhm.jpg',
id: '1bf8a8f7-18ac-4eef-919d-61d952eaa179',
allowableOperations: ['delete', 'update', 'updatePermissions'],
isFavorite: false
}
}
}
}
});
it('should raise error when getNodeInfo fails', () => {
spyOn(store, 'dispatch').and.stub();
spyOn(contentManagementService, 'getNodeInfo').and.returnValue(
throwError('error')
store.dispatch(new UploadFileVersionAction(fakeEvent));
expect(contentManagementService.versionUpdateDialog).toHaveBeenCalledWith(
fakeEvent.detail.data.node.entry,
fakeEvent.detail.files[0].file
);
uploadVersionInput.files = createFileList('bogus.txt');
uploadVersionInput.dispatchEvent(new CustomEvent('change'));
expect(store.dispatch).toHaveBeenCalledWith(
new SnackbarErrorAction('VERSION.ERROR.GENERIC')
);
expect(effects.uploadAndUnlock).not.toHaveBeenCalled();
});
});
});

View File

@ -37,9 +37,10 @@ import { FileModel, FileUtils, UploadService } from '@alfresco/adf-core';
import { Injectable, NgZone, RendererFactory2 } from '@angular/core';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { Store } from '@ngrx/store';
import { forkJoin, of } from 'rxjs';
import { tap, filter, catchError, flatMap, map, take } from 'rxjs/operators';
import { of } from 'rxjs';
import { catchError, map, take } from 'rxjs/operators';
import { ContentManagementService } from '../../services/content-management.service';
import { MinimalNodeEntryEntity } from '@alfresco/js-api';
@Injectable()
export class UploadEffects {
@ -69,9 +70,9 @@ export class UploadEffects {
this.fileVersionInput.id = 'app-upload-file-version';
this.fileVersionInput.type = 'file';
this.fileVersionInput.style.display = 'none';
this.fileVersionInput.addEventListener('change', () =>
this.uploadVersion()
);
this.fileVersionInput.addEventListener('change', () => {
this.uploadVersion();
});
renderer.appendChild(document.body, this.fileVersionInput);
this.folderInput = renderer.createElement('input') as HTMLInputElement;
@ -103,55 +104,34 @@ export class UploadEffects {
@Effect({ dispatch: false })
uploadVersion$ = this.actions$.pipe(
ofType<UploadFileVersionAction>(UploadActionTypes.UploadFileVersion),
map(() => {
map(action => {
if (action && action.payload) {
const node = action.payload.detail.data.node.entry;
const file: any = action.payload.detail.files[0].file;
this.contentService.versionUpdateDialog(node, file);
} else if (!action.payload) {
this.fileVersionInput.click();
}
})
);
private uploadVersion() {
uploadVersion() {
this.contentService
.versionUploadDialog()
.afterClosed()
.getNodeInfo()
.pipe(
tap(form => {
if (!form) {
this.fileVersionInput.value = '';
}
}),
filter(form => !!form),
flatMap(form =>
forkJoin(
of(form),
this.contentService.getNodeInfo().pipe(
catchError(_ => {
this.store.dispatch(
new SnackbarErrorAction('VERSION.ERROR.GENERIC')
);
this.store.dispatch(new SnackbarErrorAction('VERSION.ERROR.GENERIC'));
return of(null);
})
)
)
)
)
.subscribe(([form, node]) => {
if (form && node) {
const file: any = this.fileVersionInput.files[0];
const fileModel = new FileModel(
file,
{
comment: form.comment,
majorVersion: form.version,
parentId: node.parentId,
path: (file.webkitRelativePath || '').replace(/\/[^\/]*$/, ''),
newVersion: true,
nodeType: 'cm:content'
},
node.id
.subscribe((node: MinimalNodeEntryEntity) => {
if (node) {
this.contentService.versionUpdateDialog(
node,
this.fileVersionInput.files[0]
);
this.uploadAndUnlock(fileModel);
}
this.fileVersionInput.value = '';
}
});
}