[ADF-5426] Remove compatibility layer from Lib (#7110)

* remove compatibility step 1

* remove compatibility step 2

* remove compatibility step 3

* remove compatibility step 4

* remove compatibility step 5
This commit is contained in:
Eugenio Romano
2021-08-04 17:31:35 +02:00
committed by GitHub
parent 5d5b582e32
commit f30b20cc46
113 changed files with 1375 additions and 2348 deletions

View File

@@ -17,9 +17,11 @@
import { Component, Inject, OnInit, ViewEncapsulation } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DownloadEntry, NodeEntry } from '@alfresco/js-api';
import { DownloadEntry, MinimalNode } from '@alfresco/js-api';
import { LogService } from '../../services/log.service';
import { DownloadZipService } from '../../services/download-zip.service';
import { ContentService } from '../../services/content.service';
import { NodesApiService } from '../../services/nodes-api.service';
@Component({
selector: 'adf-download-zip-dialog',
@@ -38,7 +40,9 @@ export class DownloadZipDialogComponent implements OnInit {
@Inject(MAT_DIALOG_DATA)
public data: any,
private logService: LogService,
private downloadZipService: DownloadZipService) {
private downloadZipService: DownloadZipService,
private nodeService: NodesApiService,
private contentService: ContentService) {
}
ngOnInit() {
@@ -62,11 +66,11 @@ export class DownloadZipDialogComponent implements OnInit {
this.downloadZipService.createDownload({ nodeIds }).subscribe((data: DownloadEntry) => {
if (data && data.entry && data.entry.id) {
const url = this.downloadZipService.getContentUrl(data.entry.id, true);
const url = this.contentService.getContentUrl(data.entry.id, true);
this.downloadZipService.getNode(data.entry.id).subscribe((downloadNode: NodeEntry) => {
this.nodeService.getNode(data.entry.id).subscribe((downloadNode: MinimalNode) => {
this.logService.log(downloadNode);
const fileName = downloadNode.entry.name;
const fileName = downloadNode.name;
this.downloadId = data.entry.id;
this.waitAndDownload(data.entry.id, url, fileName);
});

View File

@@ -36,7 +36,6 @@ class TestComponent {
describe('LibraryFavoriteDirective', () => {
let fixture: ComponentFixture<TestComponent>;
let api: AlfrescoApiService;
let component: TestComponent;
let selection: LibraryEntity;
@@ -50,45 +49,44 @@ describe('LibraryFavoriteDirective', () => {
});
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
api = TestBed.inject(AlfrescoApiService);
selection = { entry: { guid: 'guid', id: 'id', title: 'Site', visibility: 'PUBLIC' }, isLibrary: true, isFavorite: false };
component.selection = selection;
});
it('should not check for favorite if no selection exists', () => {
spyOn(api.peopleApi, 'getFavoriteSite');
spyOn(component.directive['favoritesApi'], 'getFavoriteSite');
fixture.detectChanges();
expect(api.peopleApi.getFavoriteSite).not.toHaveBeenCalled();
expect(component.directive['favoritesApi'].getFavoriteSite).not.toHaveBeenCalled();
});
it('should mark selection as favorite', async () => {
spyOn(api.peopleApi, 'getFavoriteSite').and.returnValue(Promise.resolve(null));
spyOn(component.directive['favoritesApi'], 'getFavoriteSite').and.returnValue(Promise.resolve(null));
delete selection.isFavorite;
fixture.detectChanges();
await fixture.whenStable();
expect(api.peopleApi.getFavoriteSite).toHaveBeenCalled();
expect(component.directive['favoritesApi'].getFavoriteSite).toHaveBeenCalled();
expect(component.directive.isFavorite()).toBe(true);
});
it('should mark selection not favorite', async () => {
spyOn(api.peopleApi, 'getFavoriteSite').and.returnValue(Promise.reject());
spyOn(component.directive['favoritesApi'], 'getFavoriteSite').and.returnValue(Promise.reject());
delete selection.isFavorite;
fixture.detectChanges();
await fixture.whenStable();
expect(api.peopleApi.getFavoriteSite).toHaveBeenCalled();
expect(component.directive['favoritesApi'].getFavoriteSite).toHaveBeenCalled();
expect(component.directive.isFavorite()).toBe(false);
});
it('should call addFavorite() on click event when selection is not a favorite', async () => {
spyOn(api.peopleApi, 'getFavoriteSite').and.returnValue(Promise.reject());
spyOn(api.peopleApi, 'addFavorite').and.returnValue(Promise.resolve(null));
spyOn(component.directive['favoritesApi'], 'getFavoriteSite').and.returnValue(Promise.reject());
spyOn(component.directive['favoritesApi'], 'createFavorite').and.returnValue(Promise.resolve(null));
fixture.detectChanges();
await fixture.whenStable();
@@ -97,12 +95,12 @@ describe('LibraryFavoriteDirective', () => {
fixture.nativeElement.querySelector('button').dispatchEvent(new MouseEvent('click'));
fixture.detectChanges();
expect(api.peopleApi.addFavorite).toHaveBeenCalled();
expect(component.directive['favoritesApi'].createFavorite).toHaveBeenCalled();
});
it('should call removeFavoriteSite() on click event when selection is favorite', async () => {
spyOn(api.peopleApi, 'getFavoriteSite').and.returnValue(Promise.resolve(null));
spyOn(api.favoritesApi, 'removeFavoriteSite').and.returnValue(Promise.resolve());
spyOn(component.directive['favoritesApi'], 'getFavoriteSite').and.returnValue(Promise.resolve(null));
spyOn(component.directive['favoritesApi'], 'deleteFavorite').and.returnValue(Promise.resolve());
selection.isFavorite = true;
@@ -116,6 +114,6 @@ describe('LibraryFavoriteDirective', () => {
fixture.detectChanges();
await fixture.whenStable();
expect(api.favoritesApi.removeFavoriteSite).toHaveBeenCalled();
expect(component.directive['favoritesApi'].deleteFavorite).toHaveBeenCalled();
});
});

View File

@@ -16,7 +16,7 @@
*/
import { Directive, HostListener, Input, OnChanges, Output, EventEmitter } from '@angular/core';
import { SiteBody, FavoriteBody, FavoriteEntry, Site } from '@alfresco/js-api';
import { SiteBody, FavoriteBody, FavoriteEntry, Site, FavoritesApi } from '@alfresco/js-api';
import { AlfrescoApiService } from '../services/alfresco-api.service';
export interface LibraryEntity {
@@ -38,6 +38,7 @@ export class LibraryFavoriteDirective implements OnChanges {
@Output() error = new EventEmitter<any>();
private targetLibrary = null;
private favoritesApi: FavoritesApi;
@HostListener('click')
onClick() {
@@ -56,7 +57,9 @@ export class LibraryFavoriteDirective implements OnChanges {
}
}
constructor(private alfrescoApiService: AlfrescoApiService) {}
constructor(private alfrescoApiService: AlfrescoApiService) {
this.favoritesApi = new FavoritesApi(this.alfrescoApiService.getInstance());
}
ngOnChanges(changes) {
if (!changes.library.currentValue) {
@@ -75,7 +78,7 @@ export class LibraryFavoriteDirective implements OnChanges {
private async markFavoriteLibrary(library: LibraryEntity) {
if (this.targetLibrary.isFavorite === undefined) {
try {
await this.alfrescoApiService.peopleApi.getFavoriteSite('-me-', library.entry.id);
await this.favoritesApi.getFavoriteSite('-me-', library.entry.id);
this.targetLibrary.isFavorite = true;
} catch {
this.targetLibrary.isFavorite = false;
@@ -86,8 +89,8 @@ export class LibraryFavoriteDirective implements OnChanges {
}
private addFavorite(favoriteBody: FavoriteBody) {
this.alfrescoApiService.peopleApi
.addFavorite('-me-', favoriteBody)
this.favoritesApi
.createFavorite('-me-', favoriteBody)
.then((libraryEntry: FavoriteEntry) => {
this.targetLibrary.isFavorite = true;
this.toggle.emit(libraryEntry);
@@ -96,8 +99,8 @@ export class LibraryFavoriteDirective implements OnChanges {
}
private removeFavorite(favoriteId: string) {
this.alfrescoApiService.favoritesApi
.removeFavoriteSite('-me-', favoriteId)
this.favoritesApi
.deleteFavorite('-me-', favoriteId)
.then((libraryBody: SiteBody) => {
this.targetLibrary.isFavorite = false;
this.toggle.emit(libraryBody);

View File

@@ -28,7 +28,6 @@ import { CoreTestingModule } from '../testing/core.testing.module';
describe('LibraryMembershipDirective', () => {
let alfrescoApiService: AlfrescoApiService;
let directive: LibraryMembershipDirective;
let peopleApi: any;
let sitesService: SitesService;
let addMembershipSpy: jasmine.Spy;
let getMembershipSpy: jasmine.Spy;
@@ -64,7 +63,6 @@ describe('LibraryMembershipDirective', () => {
alfrescoApiService = TestBed.inject(AlfrescoApiService);
sitesService = TestBed.inject(SitesService);
peopleApi = alfrescoApiService.getInstance().core.peopleApi;
directive = new LibraryMembershipDirective(alfrescoApiService, sitesService, {
ecmProductInfo$: new Subject(),
isVersionSupported: () => mockSupportedVersion
@@ -73,7 +71,7 @@ describe('LibraryMembershipDirective', () => {
describe('markMembershipRequest', () => {
beforeEach(() => {
getMembershipSpy = spyOn(peopleApi, 'getSiteMembershipRequest').and.returnValue(Promise.resolve({ entry: requestedMembershipResponse }));
getMembershipSpy = spyOn(directive['sitesApi'], 'getSiteMembershipRequestForPerson').and.returnValue(Promise.resolve({ entry: requestedMembershipResponse }));
});
it('should not check membership requests if no entry is selected', fakeAsync(() => {
@@ -114,9 +112,9 @@ describe('LibraryMembershipDirective', () => {
describe('toggleMembershipRequest', () => {
beforeEach(() => {
mockSupportedVersion = false;
getMembershipSpy = spyOn(peopleApi, 'getSiteMembershipRequest').and.returnValue(Promise.resolve({ entry: requestedMembershipResponse }));
addMembershipSpy = spyOn(peopleApi, 'addSiteMembershipRequest').and.returnValue(Promise.resolve({ entry: requestedMembershipResponse }));
deleteMembershipSpy = spyOn(peopleApi, 'removeSiteMembershipRequest').and.returnValue(Promise.resolve({}));
getMembershipSpy = spyOn(directive['sitesApi'], 'getSiteMembershipRequestForPerson').and.returnValue(Promise.resolve({ entry: requestedMembershipResponse }));
addMembershipSpy = spyOn(directive['sitesApi'], 'createSiteMembershipRequestForPerson').and.returnValue(Promise.resolve({ entry: requestedMembershipResponse }));
deleteMembershipSpy = spyOn(directive['sitesApi'], 'deleteSiteMembershipRequestForPerson').and.returnValue(Promise.resolve({}));
});
it('should do nothing if there is no selected library ', fakeAsync(() => {

View File

@@ -16,7 +16,13 @@
*/
import { Directive, EventEmitter, HostListener, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
import { SiteEntry, SiteMembershipRequestBody, SiteMemberEntry, SiteMembershipRequestEntry } from '@alfresco/js-api';
import {
SiteEntry,
SiteMembershipRequestBody,
SiteMemberEntry,
SiteMembershipRequestEntry,
SitesApi
} from '@alfresco/js-api';
import { BehaviorSubject, from, Observable } from 'rxjs';
import { AlfrescoApiService } from '../services/alfresco-api.service';
import { SitesService } from '../services/sites.service';
@@ -42,6 +48,8 @@ export class LibraryMembershipDirective implements OnChanges {
isJoinRequested: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
private sitesApi: SitesApi;
/** Site for which to toggle the membership request. */
@Input('adf-library-membership')
selection: SiteEntry = null;
@@ -66,7 +74,9 @@ export class LibraryMembershipDirective implements OnChanges {
private alfrescoApiService: AlfrescoApiService,
private sitesService: SitesService,
private versionCompatibilityService: VersionCompatibilityService
) {}
) {
this.sitesApi = new SitesApi(this.alfrescoApiService.getInstance());
}
ngOnChanges(changes: SimpleChanges) {
if (!changes.selection.currentValue || !changes.selection.currentValue.entry) {
@@ -209,7 +219,7 @@ export class LibraryMembershipDirective implements OnChanges {
if (this.versionCompatibilityService.isVersionSupported('7.0.0')) {
memberBody.client = 'workspace';
}
return from(this.alfrescoApiService.peopleApi.addSiteMembershipRequest('-me-', memberBody));
return from(this.sitesApi.createSiteMembershipRequestForPerson('-me-', memberBody));
}
private joinLibrary() {
@@ -220,10 +230,10 @@ export class LibraryMembershipDirective implements OnChanges {
}
private cancelJoinRequest() {
return from(this.alfrescoApiService.peopleApi.removeSiteMembershipRequest('-me-', this.targetSite.id));
return from(this.sitesApi.deleteSiteMembershipRequestForPerson('-me-', this.targetSite.id));
}
private getMembershipRequest() {
return from(this.alfrescoApiService.peopleApi.getSiteMembershipRequest('-me-', this.targetSite.id));
return from(this.sitesApi.getSiteMembershipRequestForPerson('-me-', this.targetSite.id));
}
}

View File

@@ -18,7 +18,6 @@
import { Component, DebugElement, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { AlfrescoApiService } from '../services/alfresco-api.service';
import { NodeDeleteDirective } from './node-delete.directive';
import { setupTestBed } from '../testing/setup-test-bed';
import { CoreTestingModule } from '../testing/core.testing.module';
@@ -84,11 +83,10 @@ describe('NodeDeleteDirective', () => {
let elementWithPermanentDelete: DebugElement;
let component: TestComponent;
let componentWithPermanentDelete: TestDeletePermanentComponent;
let alfrescoApi: AlfrescoApiService;
let nodeApi;
let deleteNodeSpy: any;
let purgeDeletedNodeSpy: any;
let disposableDelete: any;
let deleteNodePermanentSpy: any;
let purgeDeletedNodePermanentSpy: any;
setupTestBed({
imports: [
@@ -103,11 +101,6 @@ describe('NodeDeleteDirective', () => {
});
beforeEach(() => {
alfrescoApi = TestBed.inject(AlfrescoApiService);
nodeApi = alfrescoApi.nodesApi;
deleteNodeSpy = spyOn(nodeApi, 'deleteNode').and.returnValue(Promise.resolve());
purgeDeletedNodeSpy = spyOn(nodeApi, 'purgeDeletedNode').and.returnValue(Promise.resolve());
fixture = TestBed.createComponent(TestComponent);
fixtureWithPermissions = TestBed.createComponent(TestWithPermissionsComponent);
fixtureWithPermanentComponent = TestBed.createComponent(TestDeletePermanentComponent);
@@ -117,6 +110,12 @@ describe('NodeDeleteDirective', () => {
element = fixture.debugElement.query(By.directive(NodeDeleteDirective));
elementWithPermanentDelete = fixtureWithPermanentComponent.debugElement.query(By.directive(NodeDeleteDirective));
deleteNodeSpy = spyOn(component.deleteDirective['nodesApi'], 'deleteNode').and.returnValue(Promise.resolve());
deleteNodePermanentSpy = spyOn(componentWithPermanentDelete.deleteDirective['nodesApi'], 'deleteNode').and.returnValue(Promise.resolve());
purgeDeletedNodePermanentSpy = spyOn(componentWithPermanentDelete.deleteDirective['trashcanApi'], 'deleteDeletedNode').and.returnValue(Promise.resolve());
});
afterEach(() => {
@@ -357,7 +356,7 @@ describe('NodeDeleteDirective', () => {
elementWithPermanentDelete.nativeElement.click();
fixture.whenStable().then(() => {
expect(deleteNodeSpy).toHaveBeenCalledWith('1', { permanent: true });
expect(deleteNodePermanentSpy).toHaveBeenCalledWith('1', { permanent: true });
done();
});
});
@@ -374,7 +373,7 @@ describe('NodeDeleteDirective', () => {
elementWithPermanentDelete.nativeElement.click();
fixture.whenStable().then(() => {
expect(purgeDeletedNodeSpy).toHaveBeenCalledWith('1');
expect(purgeDeletedNodePermanentSpy).toHaveBeenCalledWith('1');
done();
});
});

View File

@@ -18,7 +18,7 @@
/* tslint:disable:no-input-rename */
import { Directive, ElementRef, EventEmitter, HostListener, Input, OnChanges, Output } from '@angular/core';
import { NodeEntry, Node, DeletedNodeEntity, DeletedNode } from '@alfresco/js-api';
import { NodeEntry, Node, DeletedNodeEntity, DeletedNode, TrashcanApi, NodesApi } from '@alfresco/js-api';
import { Observable, forkJoin, from, of } from 'rxjs';
import { AlfrescoApiService } from '../services/alfresco-api.service';
import { TranslationService } from '../services/translation.service';
@@ -62,6 +62,9 @@ export class NodeDeleteDirective implements OnChanges {
@Output()
delete: EventEmitter<any> = new EventEmitter();
private trashcanApi: TrashcanApi;
private nodesApi: NodesApi;
@HostListener('click')
onClick() {
this.process(this.selection);
@@ -70,6 +73,8 @@ export class NodeDeleteDirective implements OnChanges {
constructor(private alfrescoApiService: AlfrescoApiService,
private translation: TranslationService,
private elementRef: ElementRef) {
this.trashcanApi = new TrashcanApi(this.alfrescoApiService.getInstance());
this.nodesApi = new NodesApi(this.alfrescoApiService.getInstance());
}
ngOnChanges() {
@@ -113,9 +118,9 @@ export class NodeDeleteDirective implements OnChanges {
let promise: Promise<any>;
if (node.entry.hasOwnProperty('archivedAt') && node.entry['archivedAt']) {
promise = this.alfrescoApiService.nodesApi.purgeDeletedNode(id);
promise = this.trashcanApi.deleteDeletedNode(id);
} else {
promise = this.alfrescoApiService.nodesApi.deleteNode(id, { permanent: this.permanent });
promise = this.nodesApi.deleteNode(id, { permanent: this.permanent });
}
return from(promise).pipe(

View File

@@ -18,7 +18,7 @@
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { MatDialog } from '@angular/material/dialog';
import { Component, DebugElement } from '@angular/core';
import { Component, DebugElement, ViewChild } from '@angular/core';
import { setupTestBed } from '../testing/setup-test-bed';
import { AlfrescoApiService } from '../services/alfresco-api.service';
import { NodeDownloadDirective } from './node-download.directive';
@@ -29,6 +29,9 @@ import { TranslateModule } from '@ngx-translate/core';
template: '<div [adfNodeDownload]="selection" [version]="version"></div>'
})
class TestComponent {
@ViewChild(NodeDownloadDirective, { static: true })
downloadDirective: NodeDownloadDirective;
selection;
version;
}
@@ -65,7 +68,7 @@ describe('NodeDownloadDirective', () => {
element = fixture.debugElement.query(By.directive(NodeDownloadDirective));
dialog = TestBed.inject(MatDialog);
apiService = TestBed.inject(AlfrescoApiService);
contentService = apiService.getInstance().content;
contentService = component.downloadDirective['contentApi'];
dialogSpy = spyOn(dialog, 'open');
});

View File

@@ -19,7 +19,7 @@ import { Directive, Input, HostListener } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { AlfrescoApiService } from '../services/alfresco-api.service';
import { DownloadZipDialogComponent } from '../dialogs/download-zip/download-zip.dialog';
import { NodeEntry, VersionEntry } from '@alfresco/js-api';
import { ContentApi, NodeEntry, VersionEntry } from '@alfresco/js-api';
import { DownloadService } from '../services/download.service';
/**
@@ -31,6 +31,8 @@ import { DownloadService } from '../services/download.service';
})
export class NodeDownloadDirective {
private contentApi: ContentApi;
/** Nodes to download. */
@Input('adfNodeDownload')
nodes: NodeEntry | NodeEntry[];
@@ -48,6 +50,7 @@ export class NodeDownloadDirective {
private apiService: AlfrescoApiService,
private downloadService: DownloadService,
private dialog: MatDialog) {
this.contentApi = new ContentApi(this.apiService.getInstance());
}
/**
@@ -101,16 +104,15 @@ export class NodeDownloadDirective {
private downloadFile(node: NodeEntry) {
if (node && node.entry) {
const contentApi = this.apiService.getInstance().content;
// nodeId for Shared node
const id = (<any> node.entry).nodeId || node.entry.id;
let url, fileName;
if (this.version) {
url = contentApi.getVersionContentUrl(id, this.version.entry.id, true);
url = this.contentApi.getVersionContentUrl(id, this.version.entry.id, true);
fileName = this.version.entry.name;
} else {
url = contentApi.getContentUrl(id, true);
url = this.contentApi.getContentUrl(id, true);
fileName = node.entry.name;
}

View File

@@ -72,7 +72,7 @@ describe('NodeFavoriteDirective', () => {
});
it('should reset favorites if selection is empty', fakeAsync(() => {
spyOn(alfrescoApiService.getInstance().core.favoritesApi, 'getFavorite').and.returnValue(Promise.resolve(null));
spyOn(directive['favoritesApi'], 'getFavorite').and.returnValue(Promise.resolve(null));
const selection = [
{ entry: { id: '1', name: 'name1' } }
@@ -96,7 +96,7 @@ describe('NodeFavoriteDirective', () => {
let favoritesApiSpy;
beforeEach(() => {
favoritesApiSpy = spyOn(alfrescoApiService.getInstance().core.favoritesApi, 'getFavorite')
favoritesApiSpy = spyOn(directive['favoritesApi'], 'getFavorite')
.and.returnValue(Promise.resolve(null));
});
@@ -177,8 +177,8 @@ describe('NodeFavoriteDirective', () => {
let addFavoriteSpy;
beforeEach(() => {
removeFavoriteSpy = spyOn(alfrescoApiService.getInstance().core.favoritesApi, 'removeFavoriteSite').and.callThrough();
addFavoriteSpy = spyOn(alfrescoApiService.getInstance().core.favoritesApi, 'addFavorite').and.callThrough();
removeFavoriteSpy = spyOn(directive['favoritesApi'], 'deleteFavorite').and.callThrough();
addFavoriteSpy = spyOn(directive['favoritesApi'], 'createFavorite').and.callThrough();
});
afterEach(() => {
@@ -326,7 +326,7 @@ describe('NodeFavoriteDirective', () => {
describe('getFavorite()', () => {
it('should not hit server when using 6.x api', fakeAsync(() => {
spyOn(alfrescoApiService.favoritesApi, 'getFavorite').and.callThrough();
spyOn(directive['favoritesApi'], 'getFavorite').and.callThrough();
const selection = [
{ entry: { id: '1', name: 'name1', isFavorite: true } }
@@ -337,11 +337,11 @@ describe('NodeFavoriteDirective', () => {
tick();
expect(directive.favorites[0].entry.isFavorite).toBe(true);
expect(alfrescoApiService.favoritesApi.getFavorite).not.toHaveBeenCalled();
expect(directive['favoritesApi'].getFavorite).not.toHaveBeenCalled();
}));
it('should process node as favorite', fakeAsync(() => {
spyOn(alfrescoApiService.getInstance().core.favoritesApi, 'getFavorite').and.returnValue(Promise.resolve(null));
spyOn(directive['favoritesApi'], 'getFavorite').and.returnValue(Promise.resolve(null));
const selection = [
{ entry: { id: '1', name: 'name1' } }
@@ -355,7 +355,7 @@ describe('NodeFavoriteDirective', () => {
}));
it('should not process node as favorite', fakeAsync(() => {
spyOn(alfrescoApiService.getInstance().core.favoritesApi, 'getFavorite').and.returnValue(Promise.reject({}));
spyOn(directive['favoritesApi'], 'getFavorite').and.returnValue(Promise.reject({}));
const selection = [
{ entry: { id: '1', name: 'name1' } }

View File

@@ -18,7 +18,7 @@
/* tslint:disable:no-input-rename */
import { Directive, EventEmitter, HostListener, Input, OnChanges, Output } from '@angular/core';
import { FavoriteBody, NodeEntry, SharedLinkEntry, Node, SharedLink } from '@alfresco/js-api';
import { FavoriteBody, NodeEntry, SharedLinkEntry, Node, SharedLink, FavoritesApi } from '@alfresco/js-api';
import { Observable, from, forkJoin, of } from 'rxjs';
import { AlfrescoApiService } from '../services/alfresco-api.service';
import { catchError, map } from 'rxjs/operators';
@@ -30,6 +30,8 @@ import { catchError, map } from 'rxjs/operators';
export class NodeFavoriteDirective implements OnChanges {
favorites: any[] = [];
private favoritesApi: FavoritesApi;
/** Array of nodes to toggle as favorites. */
@Input('adf-node-favorite')
selection: NodeEntry[] = [];
@@ -46,6 +48,7 @@ export class NodeFavoriteDirective implements OnChanges {
}
constructor(private alfrescoApiService: AlfrescoApiService) {
this.favoritesApi = new FavoritesApi(this.alfrescoApiService.getInstance());
}
ngOnChanges(changes) {
@@ -70,7 +73,7 @@ export class NodeFavoriteDirective implements OnChanges {
// shared files have nodeId
const id = (<SharedLinkEntry> selected).entry.nodeId || selected.entry.id;
return from(this.alfrescoApiService.favoritesApi.removeFavoriteSite('-me-', id));
return from(this.favoritesApi.deleteFavorite('-me-', id));
});
forkJoin(batch).subscribe(
@@ -86,7 +89,7 @@ export class NodeFavoriteDirective implements OnChanges {
const notFavorite = this.favorites.filter((node) => !node.entry.isFavorite);
const body: FavoriteBody[] = notFavorite.map((node) => this.createFavoriteBody(node));
from(this.alfrescoApiService.favoritesApi.addFavorite('-me-', <any> body))
from(this.favoritesApi.createFavorite('-me-', <any> body))
.subscribe(
() => {
notFavorite.map((selected) => selected.entry.isFavorite = true);
@@ -133,9 +136,9 @@ export class NodeFavoriteDirective implements OnChanges {
// ACS 5.x and 6.x without 'isFavorite' include
const { name, isFile, isFolder } = <Node> node;
const id = (<SharedLink> node).nodeId || node.id;
const id = (<SharedLink> node).nodeId || node.id;
const promise = this.alfrescoApiService.favoritesApi.getFavorite('-me-', id);
const promise = this.favoritesApi.getFavorite('-me-', id);
return from(promise).pipe(
map(() => ({

View File

@@ -18,7 +18,6 @@
import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { AlfrescoApiService } from '../services/alfresco-api.service';
import { NodeRestoreDirective } from './node-restore.directive';
import { setupTestBed } from '../testing/setup-test-bed';
import { TranslationService } from '../services/translation.service';
@@ -41,9 +40,7 @@ describe('NodeRestoreDirective', () => {
let fixture: ComponentFixture<TestComponent>;
let element: DebugElement;
let component: TestComponent;
let alfrescoService: AlfrescoApiService;
let nodesService;
let coreApi;
let trashcanApi;
let directiveInstance;
let restoreNodeSpy: any;
let translationService: TranslationService;
@@ -64,12 +61,10 @@ describe('NodeRestoreDirective', () => {
element = fixture.debugElement.query(By.directive(NodeRestoreDirective));
directiveInstance = element.injector.get(NodeRestoreDirective);
alfrescoService = TestBed.inject(AlfrescoApiService);
nodesService = alfrescoService.getInstance().nodes;
coreApi = alfrescoService.getInstance().core;
trashcanApi = directiveInstance['trashcanApi'];
restoreNodeSpy = spyOn(nodesService, 'restoreNode').and.returnValue(Promise.resolve());
spyOn(coreApi.nodesApi, 'getDeletedNodes').and.returnValue(Promise.resolve({
restoreNodeSpy = spyOn(trashcanApi, 'restoreDeletedNode').and.returnValue(Promise.resolve());
spyOn(trashcanApi, 'listDeletedNodes').and.returnValue(Promise.resolve({
list: { entries: [] }
}));
@@ -83,7 +78,7 @@ describe('NodeRestoreDirective', () => {
fixture.detectChanges();
element.triggerEventHandler('click', null);
expect(nodesService.restoreNode).not.toHaveBeenCalled();
expect(trashcanApi.restoreDeletedNode).not.toHaveBeenCalled();
});
it('should not restore nodes when selection has nodes without path', (done) => {
@@ -93,7 +88,7 @@ describe('NodeRestoreDirective', () => {
fixture.whenStable().then(() => {
element.triggerEventHandler('click', null);
expect(nodesService.restoreNode).not.toHaveBeenCalled();
expect(trashcanApi.restoreDeletedNode).not.toHaveBeenCalled();
done();
});
});
@@ -104,7 +99,7 @@ describe('NodeRestoreDirective', () => {
fixture.detectChanges();
element.triggerEventHandler('click', null);
fixture.whenStable().then(() => {
expect(nodesService.restoreNode).toHaveBeenCalled();
expect(trashcanApi.restoreDeletedNode).toHaveBeenCalled();
done();
});
});

View File

@@ -18,7 +18,7 @@
/* tslint:disable:component-selector no-input-rename */
import { Directive, EventEmitter, HostListener, Input, Output } from '@angular/core';
import { DeletedNodeEntry, DeletedNodesPaging, PathInfoEntity } from '@alfresco/js-api';
import { TrashcanApi, DeletedNodeEntry, DeletedNodesPaging, PathInfoEntity } from '@alfresco/js-api';
import { Observable, forkJoin, from, of } from 'rxjs';
import { AlfrescoApiService } from '../services/alfresco-api.service';
import { TranslationService } from '../services/translation.service';
@@ -35,6 +35,7 @@ export class RestoreMessageModel {
})
export class NodeRestoreDirective {
private readonly restoreProcessStatus;
private trashcanApi: TrashcanApi;
/** Array of deleted nodes to restore. */
@Input('adf-restore')
@@ -52,6 +53,7 @@ export class NodeRestoreDirective {
constructor(private alfrescoApiService: AlfrescoApiService,
private translation: TranslationService) {
this.restoreProcessStatus = this.processStatus();
this.trashcanApi = new TrashcanApi(this.alfrescoApiService.getInstance());
}
private recover(selection: any) {
@@ -100,8 +102,7 @@ export class NodeRestoreDirective {
}
private getDeletedNodes(): Observable<DeletedNodesPaging> {
const promise = this.alfrescoApiService.getInstance()
.core.nodesApi.getDeletedNodes({ include: ['path'] });
const promise = this.trashcanApi.listDeletedNodes({ include: ['path'] });
return from(promise);
}
@@ -109,7 +110,7 @@ export class NodeRestoreDirective {
private restoreNode(node): Observable<any> {
const { entry } = node;
const promise = this.alfrescoApiService.getInstance().nodes.restoreNode(entry.id);
const promise = this.trashcanApi.restoreDeletedNode(entry.id);
return from(promise).pipe(
map(() => ({

View File

@@ -27,12 +27,28 @@ import { TabModel } from './tab.model';
import { fakeMetadataForm, fakeViewerForm } from 'process-services-cloud/src/lib/form/mocks/cloud-form.mock';
import { Node } from '@alfresco/js-api';
import { UploadWidgetContentLinkModel } from './upload-widget-content-link.model';
import { AlfrescoApiService } from '../../../../services';
import { TestBed } from '@angular/core/testing';
import { CoreTestingModule, setupTestBed } from '../../../../testing';
import { TranslateModule } from '@ngx-translate/core';
import { CoreModule } from '../../../../core.module';
describe('FormModel', () => {
let formService: FormService;
let alfrescoApiService: AlfrescoApiService;
setupTestBed({
imports: [
TranslateModule.forRoot(),
CoreModule.forRoot(),
CoreTestingModule
]
});
beforeEach(() => {
formService = new FormService(null, null, null);
alfrescoApiService = TestBed.inject(AlfrescoApiService);
formService = new FormService(null, alfrescoApiService, null);
});
it('should store original json', () => {

View File

@@ -28,6 +28,7 @@ import { DropdownEditorComponent } from './dropdown.editor';
import { setupTestBed } from '../../../../../../testing/setup-test-bed';
import { CoreTestingModule } from '../../../../../../testing/core.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { AlfrescoApiService } from '../../../../../../services';
describe('DropdownEditorComponent', () => {
@@ -37,6 +38,7 @@ describe('DropdownEditorComponent', () => {
let table: DynamicTableModel;
let column: DynamicTableColumn;
let row: DynamicTableRow;
let alfrescoApiService: AlfrescoApiService;
setupTestBed({
imports: [
@@ -46,7 +48,8 @@ describe('DropdownEditorComponent', () => {
});
beforeEach(() => {
formService = new FormService(null, null, null);
alfrescoApiService = TestBed.inject(AlfrescoApiService);
formService = new FormService(null, alfrescoApiService, null);
row = <DynamicTableRow> {value: {dropdown: 'one'}};
column = <DynamicTableColumn> {

View File

@@ -22,15 +22,29 @@ import { DynamicTableColumn } from './../dynamic-table-column.model';
import { DynamicTableRow } from './../dynamic-table-row.model';
import { DynamicTableModel } from './../dynamic-table.widget.model';
import { RowEditorComponent } from './row.editor';
import { AlfrescoApiService } from '../../../../../services';
import { TestBed } from '@angular/core/testing';
import { CoreTestingModule, setupTestBed } from '../../../../../testing';
import { TranslateModule } from '@ngx-translate/core';
describe('RowEditorComponent', () => {
let component: RowEditorComponent;
let alfrescoApiService: AlfrescoApiService;
setupTestBed({
imports: [
TranslateModule.forRoot(),
CoreTestingModule
]
});
beforeEach(() => {
alfrescoApiService = TestBed.inject(AlfrescoApiService);
component = new RowEditorComponent();
const field = new FormFieldModel(new FormModel());
component.table = new DynamicTableModel(field, new FormService(null, null, null));
component.table = new DynamicTableModel(field, new FormService(null, alfrescoApiService, null));
component.row = <DynamicTableRow> {};
component.column = <DynamicTableColumn> {};
});

View File

@@ -22,14 +22,28 @@ import { FormFieldModel } from '../core/form-field.model';
import { FormModel } from '../core/form.model';
import { GroupModel } from '../core/group.model';
import { FunctionalGroupWidgetComponent } from './functional-group.widget';
import { AlfrescoApiService } from '../../../../services';
import { TestBed } from '@angular/core/testing';
import { CoreTestingModule, setupTestBed } from '../../../../testing';
import { TranslateModule } from '@ngx-translate/core';
describe('FunctionalGroupWidgetComponent', () => {
let formService: FormService;
let elementRef: ElementRef;
let widget: FunctionalGroupWidgetComponent;
let alfrescoApiService: AlfrescoApiService;
setupTestBed({
imports: [
TranslateModule.forRoot(),
CoreTestingModule
]
});
beforeEach(() => {
formService = new FormService(null, null, null);
alfrescoApiService = TestBed.inject(AlfrescoApiService);
formService = new FormService(null, alfrescoApiService, null);
elementRef = new ElementRef(null);
widget = new FunctionalGroupWidgetComponent(formService, elementRef);
widget.field = new FormFieldModel(new FormModel());

View File

@@ -30,11 +30,13 @@ import { MatRadioModule } from '@angular/material/radio';
import { FormsModule } from '@angular/forms';
import { CoreTestingModule } from '../../../../testing';
import { TranslateModule } from '@ngx-translate/core';
import { AlfrescoApiService } from '../../../../services';
describe('RadioButtonsWidgetComponent', () => {
let formService: FormService;
let widget: RadioButtonsWidgetComponent;
let alfrescoApiService: AlfrescoApiService;
setupTestBed({
imports: [
@@ -47,7 +49,9 @@ describe('RadioButtonsWidgetComponent', () => {
});
beforeEach(() => {
formService = new FormService(null, null, null);
alfrescoApiService = TestBed.inject(AlfrescoApiService);
formService = new FormService(null, alfrescoApiService, null);
widget = new RadioButtonsWidgetComponent(formService, null);
widget.field = new FormFieldModel(new FormModel(), { restUrl: '<url>' });
});

View File

@@ -28,12 +28,14 @@ import { TypeaheadWidgetComponent } from './typeahead.widget';
import { setupTestBed } from '../../../../testing/setup-test-bed';
import { TranslateService, TranslateModule } from '@ngx-translate/core';
import { CoreTestingModule } from '../../../../testing/core.testing.module';
import { AlfrescoApiService } from '../../../../services';
describe('TypeaheadWidgetComponent', () => {
let formService: FormService;
let widget: TypeaheadWidgetComponent;
let translationService: TranslateService;
let alfrescoApiService: AlfrescoApiService;
setupTestBed({
imports: [
@@ -43,11 +45,12 @@ describe('TypeaheadWidgetComponent', () => {
});
beforeEach(() => {
alfrescoApiService = TestBed.inject(AlfrescoApiService);
translationService = TestBed.inject(TranslateService);
spyOn(translationService, 'instant').and.callFake((key) => { return key; });
spyOn(translationService, 'get').and.callFake((key) => { return of(key); });
formService = new FormService(null, null, null);
formService = new FormService(null, alfrescoApiService, null);
widget = new TypeaheadWidgetComponent(formService, null);
widget.field = new FormFieldModel(new FormModel({ taskId: 'task-id' }));
widget.field.restUrl = 'whateverURL';

View File

@@ -19,7 +19,12 @@ import { AlfrescoApiService } from '../../services/alfresco-api.service';
import { LogService } from '../../services/log.service';
import { SitesService } from '../../services/sites.service';
import { Injectable } from '@angular/core';
import { AlfrescoApiCompatibility, MinimalNode, RelatedContentRepresentation } from '@alfresco/js-api';
import {
IntegrationAlfrescoOnPremiseApi,
MinimalNode,
RelatedContentRepresentation,
ActivitiContentApi
} from '@alfresco/js-api';
import { Observable, from, throwError } from 'rxjs';
import { ExternalContent } from '../components/widgets/core/external-content';
import { ExternalContentLink } from '../components/widgets/core/external-content-link';
@@ -33,9 +38,15 @@ export class ActivitiContentService {
static UNKNOWN_ERROR_MESSAGE: string = 'Unknown error';
static GENERIC_ERROR_MESSAGE: string = 'Server error';
integrationAlfrescoOnPremiseApi: IntegrationAlfrescoOnPremiseApi;
contentApi: ActivitiContentApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService,
private sitesService: SitesService) {
this.integrationAlfrescoOnPremiseApi = new IntegrationAlfrescoOnPremiseApi(this.apiService.getInstance());
this.contentApi = new ActivitiContentApi(this.apiService.getInstance());
}
/**
@@ -45,9 +56,8 @@ export class ActivitiContentService {
* @param folderId
*/
getAlfrescoNodes(accountId: string, folderId: string): Observable<[ExternalContent]> {
const apiService: AlfrescoApiCompatibility = this.apiService.getInstance();
const accountShortId = accountId.replace('alfresco-', '');
return from(apiService.activiti.alfrescoApi.getContentInFolder(accountShortId, folderId))
return from(this.integrationAlfrescoOnPremiseApi.getContentInFolder(accountShortId, folderId))
.pipe(
map(this.toJsonArray),
catchError((err) => this.handleError(err))
@@ -60,12 +70,11 @@ export class ActivitiContentService {
* @param includeAccount
*/
getAlfrescoRepositories(tenantId?: number, includeAccount?: boolean): Observable<any> {
const apiService: AlfrescoApiCompatibility = this.apiService.getInstance();
const opts = {
tenantId,
includeAccounts: includeAccount ? includeAccount : true
};
return from(apiService.activiti.alfrescoApi.getRepositories(opts))
return from(this.integrationAlfrescoOnPremiseApi.getRepositories(opts))
.pipe(
map(this.toJsonArray),
catchError((err) => this.handleError(err))
@@ -80,8 +89,7 @@ export class ActivitiContentService {
* @param siteId
*/
linkAlfrescoNode(accountId: string, node: ExternalContent, siteId: string): Observable<ExternalContentLink> {
const apiService: AlfrescoApiCompatibility = this.apiService.getInstance();
return from(apiService.activiti.contentApi.createTemporaryRelatedContent({
return from(this.contentApi.createTemporaryRelatedContent({
link: true,
name: node.title,
simpleType: node.simpleType,
@@ -95,7 +103,6 @@ export class ActivitiContentService {
}
applyAlfrescoNode(node: MinimalNode, siteId: string, accountId: string) {
const apiService: AlfrescoApiCompatibility = this.apiService.getInstance();
const currentSideId = siteId ? siteId : this.sitesService.getSiteNameFromNodePath(node);
const params: RelatedContentRepresentation = {
source: accountId,
@@ -104,7 +111,7 @@ export class ActivitiContentService {
name: node.name,
link: node.isLink
};
return from(apiService.activiti.contentApi.createTemporaryRelatedContent(params))
return from(this.contentApi.createTemporaryRelatedContent(params))
.pipe(
map(this.toJson),
catchError((err) => this.handleError(err))

View File

@@ -21,6 +21,7 @@ import { Injectable } from '@angular/core';
import { Observable, from } from 'rxjs';
import { FormModel } from '../components/widgets/core/form.model';
import { map, catchError } from 'rxjs/operators';
import { CustomModelApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
@@ -31,8 +32,11 @@ export class EcmModelService {
public static MODEL_NAME: string = 'activitiFormsModel';
public static TYPE_MODEL: string = 'cm:folder';
private customModelApi: CustomModelApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.customModelApi = new CustomModelApi(this.apiService.getInstance());
}
public createEcmTypeForActivitiForm(formName: string, form: FormModel): Observable<any> {
@@ -128,7 +132,7 @@ export class EcmModelService {
}
public activeEcmModel(modelName: string): Observable<any> {
return from(this.apiService.getInstance().core.customModelApi.activateCustomModel(modelName))
return from(this.customModelApi.activateCustomModel(modelName))
.pipe(
map(this.toJson),
catchError((err) => this.handleError(err))
@@ -136,7 +140,7 @@ export class EcmModelService {
}
public createEcmModel(modelName: string, nameSpace: string): Observable<any> {
return from(this.apiService.getInstance().core.customModelApi.createCustomModel('DRAFT', '', modelName, modelName, nameSpace))
return from(this.customModelApi.createCustomModel('DRAFT', '', modelName, modelName, nameSpace))
.pipe(
map(this.toJson),
catchError((err) => this.handleError(err))
@@ -144,7 +148,7 @@ export class EcmModelService {
}
public getEcmModels(): Observable<any> {
return from(this.apiService.getInstance().core.customModelApi.getAllCustomModel())
return from(this.customModelApi.getAllCustomModel())
.pipe(
map(this.toJson),
catchError((err) => this.handleError(err))
@@ -152,7 +156,7 @@ export class EcmModelService {
}
public getEcmType(modelName: string): Observable<any> {
return from(this.apiService.getInstance().core.customModelApi.getAllCustomType(modelName))
return from(this.customModelApi.getAllCustomType(modelName))
.pipe(
map(this.toJson),
catchError((err) => this.handleError(err))
@@ -162,7 +166,7 @@ export class EcmModelService {
public createEcmType(typeName: string, modelName: string, parentType: string): Observable<any> {
const name = this.cleanNameType(typeName);
return from(this.apiService.getInstance().core.customModelApi.createCustomType(modelName, name, parentType, typeName, ''))
return from(this.customModelApi.createCustomType(modelName, name, parentType, typeName, ''))
.pipe(
map(this.toJson),
catchError((err) => this.handleError(err))
@@ -189,7 +193,7 @@ export class EcmModelService {
}
}
return from(this.apiService.getInstance().core.customModelApi.addPropertyToType(modelName, name, properties))
return from(this.customModelApi.addPropertyToType(modelName, name, properties))
.pipe(
map(this.toJson),
catchError((err) => this.handleError(err))

View File

@@ -16,7 +16,6 @@
*/
import { TestBed } from '@angular/core/testing';
import { AlfrescoApiService } from '../../services/alfresco-api.service';
import { formModelTabs } from '../../mock';
import { FormService } from './form.service';
import { setupTestBed } from '../../testing/setup-test-bed';
@@ -53,7 +52,6 @@ const fakePeopleResponse = {
describe('Form service', () => {
let service: FormService;
let apiService: AlfrescoApiService;
setupTestBed({
imports: [
@@ -64,7 +62,6 @@ describe('Form service', () => {
beforeEach(() => {
service = TestBed.inject(FormService);
apiService = TestBed.inject(AlfrescoApiService);
jasmine.Ajax.install();
});
@@ -226,22 +223,6 @@ describe('Form service', () => {
});
});
it('should get start form definition by process definition id', (done) => {
const processApiSpy = jasmine.createSpyObj(['getProcessDefinitionStartForm']);
spyOn(apiService, 'getInstance').and.returnValue({
activiti: {
processApi: processApiSpy
}
} as any);
processApiSpy.getProcessDefinitionStartForm.and.returnValue(Promise.resolve({ id: '1' }));
service.getStartFormDefinition('myprocess:1').subscribe(() => {
expect(processApiSpy.getProcessDefinitionStartForm).toHaveBeenCalledWith('myprocess:1');
done();
});
});
it('should handle error with generic message', () => {
service.handleError(null).subscribe(() => {
}, (error) => {

View File

@@ -31,9 +31,17 @@ import {
import { EcmModelService } from './ecm-model.service';
import { map, catchError, switchMap, combineAll, defaultIfEmpty } from 'rxjs/operators';
import {
Activiti,
CompleteFormRepresentation,
SaveFormRepresentation
ModelsApi,
ProcessInstanceVariablesApi,
SaveFormRepresentation,
TasksApi,
TaskFormsApi,
ProcessInstancesApi,
FormModelsApi,
ProcessDefinitionsApi,
UsersApi,
ActivitiGroupsApi
} from '@alfresco/js-api';
@Injectable({
@@ -44,6 +52,16 @@ export class FormService {
static UNKNOWN_ERROR_MESSAGE: string = 'Unknown error';
static GENERIC_ERROR_MESSAGE: string = 'Server error';
taskApi: TasksApi;
taskFormsApi: TaskFormsApi;
modelsApi: ModelsApi;
editorApi: FormModelsApi;
processDefinitionsApi: ProcessDefinitionsApi;
processInstancesApi: ProcessInstancesApi;
processInstanceVariablesApi: ProcessInstanceVariablesApi;
groupsApi: ActivitiGroupsApi;
usersApi: UsersApi;
formLoaded = new Subject<FormEvent>();
formDataRefreshed = new Subject<FormEvent>();
formFieldValueChanged = new Subject<FormFieldEvent>();
@@ -65,34 +83,16 @@ export class FormService {
constructor(private ecmModelService: EcmModelService,
private apiService: AlfrescoApiService,
protected logService: LogService) {
}
private get taskApi(): Activiti.TaskApi {
return this.apiService.getInstance().activiti.taskApi;
}
private get modelsApi(): Activiti.ModelsApi {
return this.apiService.getInstance().activiti.modelsApi;
}
private get editorApi(): Activiti.EditorApi {
return this.apiService.getInstance().activiti.editorApi;
}
private get processApi(): Activiti.ProcessApi {
return this.apiService.getInstance().activiti.processApi;
}
private get processInstanceVariablesApi(): Activiti.ProcessInstanceVariablesApi {
return this.apiService.getInstance().activiti.processInstanceVariablesApi;
}
private get usersWorkflowApi(): Activiti.UsersWorkflowApi {
return this.apiService.getInstance().activiti.usersWorkflowApi;
}
private get groupsApi(): Activiti.GroupsApi {
return this.apiService.getInstance().activiti.groupsApi;
this.taskApi = new TasksApi(this.apiService.getInstance());
this.modelsApi = new ModelsApi(this.apiService.getInstance());
this.editorApi = new FormModelsApi(this.apiService.getInstance());
this.processDefinitionsApi = new ProcessDefinitionsApi(this.apiService.getInstance());
this.processInstanceVariablesApi = new ProcessInstanceVariablesApi(this.apiService.getInstance());
this.processInstancesApi = new ProcessInstancesApi(this.apiService.getInstance());
this.usersApi = new UsersApi(this.apiService.getInstance());
this.groupsApi = new ActivitiGroupsApi(this.apiService.getInstance());
this.taskFormsApi = new TaskFormsApi(this.apiService.getInstance());
}
/**
@@ -100,6 +100,7 @@ export class FormService {
* @param json JSON to create the form
* @param data Values for the form fields
* @param readOnly Should the form fields be read-only?
* @param fixedSpace
* @returns Form model created from input data
*/
parseForm(json: any, data?: FormValues, readOnly: boolean = false, fixedSpace?: boolean): FormModel {
@@ -216,7 +217,7 @@ export class FormService {
* @returns List of process definitions
*/
getProcessDefinitions(): Observable<any> {
return from(this.processApi.getProcessDefinitions({}))
return from(this.processDefinitionsApi.getProcessDefinitions({}))
.pipe(
map(this.toJsonArray),
catchError((err) => this.handleError(err))
@@ -270,7 +271,7 @@ export class FormService {
saveTaskForm(taskId: string, formValues: FormValues): Observable<any> {
const saveFormRepresentation = <SaveFormRepresentation> { values: formValues };
return from(this.taskApi.saveTaskForm(taskId, saveFormRepresentation))
return from(this.taskFormsApi.saveTaskForm(taskId, saveFormRepresentation))
.pipe(
catchError((err) => this.handleError(err))
);
@@ -289,7 +290,7 @@ export class FormService {
completeFormRepresentation.outcome = outcome;
}
return from(this.taskApi.completeTaskForm(taskId, completeFormRepresentation))
return from(this.taskFormsApi.completeTaskForm(taskId, completeFormRepresentation))
.pipe(
catchError((err) => this.handleError(err))
);
@@ -301,7 +302,7 @@ export class FormService {
* @returns Form definition
*/
getTaskForm(taskId: string): Observable<any> {
return from(this.taskApi.getTaskForm(taskId))
return from(this.taskFormsApi.getTaskForm(taskId))
.pipe(
map(this.toJson),
catchError((err) => this.handleError(err))
@@ -346,7 +347,7 @@ export class FormService {
* @returns Form definition
*/
getStartFormInstance(processId: string): Observable<any> {
return from(this.processApi.getProcessInstanceStartForm(processId))
return from(this.processInstancesApi.getProcessInstanceStartForm(processId))
.pipe(
map(this.toJson),
catchError((err) => this.handleError(err))
@@ -359,7 +360,7 @@ export class FormService {
* @returns Process instance
*/
getProcessInstance(processId: string): Observable<any> {
return from(this.processApi.getProcessInstance(processId))
return from(this.processInstancesApi.getProcessInstance(processId))
.pipe(
map(this.toJson),
catchError((err) => this.handleError(err))
@@ -372,7 +373,7 @@ export class FormService {
* @returns Form definition
*/
getStartFormDefinition(processId: string): Observable<any> {
return from(this.processApi.getProcessDefinitionStartForm(processId))
return from(this.processDefinitionsApi.getProcessDefinitionStartForm(processId))
.pipe(
map(this.toJson),
catchError((err) => this.handleError(err))
@@ -386,7 +387,7 @@ export class FormService {
* @returns Field values
*/
getRestFieldValues(taskId: string, field: string): Observable<any> {
return from(this.taskApi.getRestFieldValues(taskId, field))
return from(this.taskFormsApi.getRestFieldValues(taskId, field))
.pipe(
catchError((err) => this.handleError(err))
);
@@ -399,7 +400,7 @@ export class FormService {
* @returns Field values
*/
getRestFieldValuesByProcessId(processDefinitionId: string, field: string): Observable<any> {
return from(this.processApi.getRestFieldValues(processDefinitionId, field))
return from(this.processDefinitionsApi.getRestFieldValues(processDefinitionId, field))
.pipe(
catchError((err) => this.handleError(err))
);
@@ -413,7 +414,7 @@ export class FormService {
* @returns Field values
*/
getRestFieldValuesColumnByProcessId(processDefinitionId: string, field: string, column?: string): Observable<any> {
return from(this.processApi.getRestTableFieldValues(processDefinitionId, field, column))
return from(this.processDefinitionsApi.getRestTableFieldValues(processDefinitionId, field, column))
.pipe(
catchError((err) => this.handleError(err))
);
@@ -427,7 +428,7 @@ export class FormService {
* @returns Field values
*/
getRestFieldValuesColumn(taskId: string, field: string, column?: string): Observable<any> {
return from(this.taskApi.getRestFieldValuesColumn(taskId, field, column))
return from(this.taskFormsApi.getRestFieldColumnValues(taskId, field, column))
.pipe(
catchError((err) => this.handleError(err))
);
@@ -439,7 +440,7 @@ export class FormService {
* @returns URL string
*/
getUserProfileImageApi(userId: string): string {
return this.apiService.getInstance().activiti.userApi.getUserProfilePictureUrl(userId);
return this.usersApi.getUserProfilePictureUrl(userId);
}
/**
@@ -453,7 +454,7 @@ export class FormService {
if (groupId) {
option.groupId = groupId;
}
return from(this.usersWorkflowApi.getUsers(option))
return from(this.usersApi.getUsers(option))
.pipe(
switchMap(response => <UserProcessModel[]> response.data || []),
map((user) => {

View File

@@ -18,7 +18,7 @@
import { AlfrescoApiService } from '../../services/alfresco-api.service';
import { LogService } from '../../services/log.service';
import { Injectable } from '@angular/core';
import { RelatedContentRepresentation } from '@alfresco/js-api';
import { ActivitiContentApi, RelatedContentRepresentation } from '@alfresco/js-api';
import { Observable, from, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
@@ -30,12 +30,11 @@ export class ProcessContentService {
static UNKNOWN_ERROR_MESSAGE: string = 'Unknown error';
static GENERIC_ERROR_MESSAGE: string = 'Server error';
private contentApi: ActivitiContentApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
}
private get contentApi(): any {
return this.apiService.getInstance().activiti.contentApi;
this.contentApi = new ActivitiContentApi(this.apiService.getInstance());
}
/**
@@ -75,7 +74,7 @@ export class ProcessContentService {
*/
getContentPreview(contentId: number): Observable<Blob> {
return new Observable((observer) => {
this.contentApi.getContentPreview(contentId).then(
this.contentApi.getRawContent(contentId).then(
(result) => {
observer.next(result);
observer.complete();
@@ -111,7 +110,7 @@ export class ProcessContentService {
* @returns Binary data of the thumbnail image
*/
getContentThumbnail(contentId: number): Observable<Blob> {
return from(this.contentApi.getContentThumbnail(contentId))
return from(this.contentApi.getRawContent(contentId, 'thumbnail'))
.pipe(catchError((err) => this.handleError(err)));
}

View File

@@ -30,17 +30,20 @@ import {
import { TaskProcessVariableModel } from '../models/task-process-variable.model';
import { WidgetVisibilityModel, WidgetTypeEnum } from '../models/widget-visibility.model';
import { map, catchError } from 'rxjs/operators';
import { TaskFormsApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
})
export class WidgetVisibilityService {
private taskFormsApi: TaskFormsApi;
private processVarList: TaskProcessVariableModel[];
private form: FormModel;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.taskFormsApi = new TaskFormsApi(this.apiService.getInstance());
}
public refreshVisibility(form: FormModel, processVarList?: TaskProcessVariableModel[]) {
@@ -319,7 +322,7 @@ export class WidgetVisibilityService {
}
getTaskProcessVariable(taskId: string): Observable<TaskProcessVariableModel[]> {
return from(this.apiService.getInstance().activiti.taskFormsApi.getTaskFormVariables(taskId))
return from(this.taskFormsApi.getTaskFormVariables(taskId))
.pipe(
map((res) => {
const jsonRes = this.toJson(res);

View File

@@ -55,13 +55,7 @@ export let mockError = {
};
export let searchMockApi: any = {
core: {
queriesApi: {
findNodes: () => Promise.resolve(fakeSearch)
}
},
isEcmLoggedIn() {
return false;
},
reply: () => ''
findNodes: () => Promise.resolve(fakeSearch)
};

View File

@@ -16,15 +16,7 @@
*/
import { Injectable } from '@angular/core';
import {
ContentApi,
Core,
Activiti,
SearchApi,
Node,
GroupsApi,
AlfrescoApiCompatibility, AlfrescoApiConfig, AspectsApi, TypesApi
} from '@alfresco/js-api';
import { Node, AlfrescoApi, AlfrescoApiConfig } from '@alfresco/js-api';
import { AppConfigService, AppConfigValues } from '../app-config/app-config.service';
import { Subject, ReplaySubject } from 'rxjs';
import { OauthConfigModel } from '../models/oauth-config.model';
@@ -43,72 +35,16 @@ export class AlfrescoApiService {
alfrescoApiInitialized: ReplaySubject<boolean> = new ReplaySubject(1);
protected alfrescoApi: AlfrescoApiCompatibility;
protected alfrescoApi: AlfrescoApi;
lastConfig: AlfrescoApiConfig;
private excludedErrorUrl: string[] = ['api/enterprise/system/properties'];
getInstance(): AlfrescoApiCompatibility {
getInstance(): AlfrescoApi {
return this.alfrescoApi;
}
get taskApi(): Activiti.TaskApi {
return this.getInstance().activiti.taskApi;
}
get contentApi(): ContentApi {
return this.getInstance().content;
}
get nodesApi(): Core.NodesApi {
return this.getInstance().nodes;
}
get renditionsApi(): Core.RenditionsApi {
return this.getInstance().core.renditionsApi;
}
get sharedLinksApi(): Core.SharedlinksApi {
return this.getInstance().core.sharedlinksApi;
}
get sitesApi(): Core.SitesApi {
return this.getInstance().core.sitesApi;
}
get favoritesApi(): Core.FavoritesApi {
return this.getInstance().core.favoritesApi;
}
get peopleApi(): Core.PeopleApi {
return this.getInstance().core.peopleApi;
}
get searchApi(): SearchApi {
return this.getInstance().search.searchApi;
}
get versionsApi(): Core.VersionsApi {
return this.getInstance().core.versionsApi;
}
get classesApi(): Core.ClassesApi {
return this.getInstance().core.classesApi;
}
get groupsApi(): GroupsApi {
return new GroupsApi(this.getInstance());
}
get aspectsApi(): AspectsApi {
return new AspectsApi(this.getInstance());
}
get typesApi(): TypesApi {
return new TypesApi(this.getInstance());
}
constructor(
protected appConfig: AppConfigService,
protected storageService: StorageService) {
@@ -148,10 +84,10 @@ export class AlfrescoApiService {
if (this.alfrescoApi && this.isDifferentConfig(this.lastConfig, config)) {
this.lastConfig = config;
this.alfrescoApi.configureJsApi(config);
this.alfrescoApi.setConfig(config);
} else {
this.lastConfig = config;
this.alfrescoApi = new AlfrescoApiCompatibility(config);
this.alfrescoApi = new AlfrescoApi(config);
}
}

View File

@@ -16,7 +16,7 @@
*/
import { Injectable } from '@angular/core';
import { AppDefinitionRepresentation } from '@alfresco/js-api';
import { RuntimeAppDefinitionsApi, AppDefinitionRepresentation } from '@alfresco/js-api';
import { Observable, from, throwError } from 'rxjs';
import { AlfrescoApiService } from './alfresco-api.service';
import { LogService } from './log.service';
@@ -27,8 +27,11 @@ import { map, catchError } from 'rxjs/operators';
})
export class AppsProcessService {
appsApi: RuntimeAppDefinitionsApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.appsApi = new RuntimeAppDefinitionsApi(this.apiService.getInstance());
}
/**
@@ -36,7 +39,7 @@ export class AppsProcessService {
* @returns The list of deployed apps
*/
getDeployedApplications(): Observable<AppDefinitionRepresentation[]> {
return from(this.apiService.getInstance().activiti.appsApi.getAppDefinitions())
return from(this.appsApi.getAppDefinitions())
.pipe(
map((response: any) => <AppDefinitionRepresentation[]> response.data),
catchError((err) => this.handleError(err))
@@ -49,7 +52,7 @@ export class AppsProcessService {
* @returns The list of deployed apps
*/
getDeployedApplicationsByName(name: string): Observable<AppDefinitionRepresentation> {
return from(this.apiService.getInstance().activiti.appsApi.getAppDefinitions())
return from(this.appsApi.getAppDefinitions())
.pipe(
map((response: any) => <AppDefinitionRepresentation> response.data.find((app) => app.name === name)),
catchError((err) => this.handleError(err))
@@ -62,7 +65,7 @@ export class AppsProcessService {
* @returns Details of the app
*/
getApplicationDetailsById(appId: number): Observable<AppDefinitionRepresentation> {
return from(this.apiService.getInstance().activiti.appsApi.getAppDefinitions())
return from(this.appsApi.getAppDefinitions())
.pipe(
map((response: any) => response.data.find((app) => app.id === appId)),
catchError((err) => this.handleError(err))

View File

@@ -22,7 +22,6 @@ import { CookieService } from './cookie.service';
import { AppConfigService } from '../app-config/app-config.service';
import { setupTestBed } from '../testing/setup-test-bed';
import { CoreTestingModule } from '../testing/core.testing.module';
import { UserRepresentation } from '@alfresco/js-api';
import { TranslateModule } from '@ngx-translate/core';
declare let jasmine: any;
@@ -189,7 +188,7 @@ describe('AuthenticationService', () => {
});
it('[ECM] should return true if kerberos configured', () => {
appConfigService.config.auth.withCredentials = true ;
appConfigService.config.auth.withCredentials = true;
expect(authService.isLoggedInWith('ECM')).toBe(true);
expect(authService.isLoggedIn()).toBe(true);
@@ -313,17 +312,6 @@ describe('AuthenticationService', () => {
expect(authService.isALLProvider()).toBe(false);
});
it('[BPM] should be able to retrieve current logged in user', (done) => {
spyOn(apiService.getInstance().activiti.profileApi, 'getProfile').and.returnValue(
Promise.resolve((<UserRepresentation> {
email: 'fake-email'
})));
authService.getBpmLoggedUser().subscribe((fakeUser) => {
expect(fakeUser.email).toBe('fake-email');
done();
});
});
});
describe('remember me', () => {
@@ -368,7 +356,8 @@ describe('AuthenticationService', () => {
it('[ECM] should not save the remember me cookie after failed login', (done) => {
const disposableLogin = authService.login('fake-username', 'fake-password').subscribe(
() => {},
() => {
},
() => {
expect(cookie['ALFRESCO_REMEMBER_ME']).toBeUndefined();
disposableLogin.unsubscribe();
@@ -425,7 +414,8 @@ describe('AuthenticationService', () => {
it('[ALL] should return login fail if only ECM call fail', (done) => {
const disposableLogin = authService.login('fake-username', 'fake-password').subscribe(
() => {},
() => {
},
() => {
expect(authService.isLoggedIn()).toBe(false, 'isLoggedIn');
expect(authService.getTicketEcm()).toBe(null, 'getTicketEcm');
@@ -447,7 +437,8 @@ describe('AuthenticationService', () => {
it('[ALL] should return login fail if only BPM call fail', (done) => {
const disposableLogin = authService.login('fake-username', 'fake-password').subscribe(
() => {},
() => {
},
() => {
expect(authService.isLoggedIn()).toBe(false);
expect(authService.getTicketEcm()).toBe(null);
@@ -470,7 +461,8 @@ describe('AuthenticationService', () => {
it('[ALL] should return ticket undefined when the credentials are wrong', (done) => {
const disposableLogin = authService.login('fake-username', 'fake-password').subscribe(
() => {},
() => {
},
() => {
expect(authService.isLoggedIn()).toBe(false);
expect(authService.getTicketEcm()).toBe(null);

View File

@@ -22,7 +22,7 @@ import { CookieService } from './cookie.service';
import { LogService } from './log.service';
import { RedirectionModel } from '../models/redirection.model';
import { AppConfigService, AppConfigValues } from '../app-config/app-config.service';
import { UserRepresentation } from '@alfresco/js-api';
import { UserProfileApi, UserRepresentation } from '@alfresco/js-api';
import { map, catchError, tap } from 'rxjs/operators';
import { HttpHeaders } from '@angular/common/http';
import { JwtHelperService } from './jwt-helper.service';
@@ -48,6 +48,8 @@ export class AuthenticationService {
*/
onLogout: ReplaySubject<any> = new ReplaySubject<any>(1);
private profileApi: UserProfileApi;
constructor(
private appConfig: AppConfigService,
private storageService: StorageService,
@@ -55,7 +57,10 @@ export class AuthenticationService {
private cookie: CookieService,
private logService: LogService) {
this.alfrescoApi.alfrescoApiInitialized.subscribe(() => {
this.alfrescoApi.getInstance().reply('logged-in', () => this.onLogin.next());
this.alfrescoApi.getInstance().reply('logged-in', () => {
this.profileApi = new UserProfileApi(alfrescoApi.getInstance());
this.onLogin.next();
});
});
}
@@ -295,7 +300,7 @@ export class AuthenticationService {
* @returns User information
*/
getBpmLoggedUser(): Observable<UserRepresentation> {
return from(this.alfrescoApi.getInstance().activiti.profileApi.getProfile());
return from(this.profileApi.getProfile());
}
private hasValidRedirection(provider: string): boolean {

View File

@@ -21,7 +21,7 @@ import { AlfrescoApiService } from './alfresco-api.service';
import { LogService } from './log.service';
import { BpmUserModel } from '../models/bpm-user.model';
import { map, catchError } from 'rxjs/operators';
import { UserRepresentation } from '@alfresco/js-api';
import { UserProfileApi, UserRepresentation } from '@alfresco/js-api';
/**
*
@@ -33,8 +33,11 @@ import { UserRepresentation } from '@alfresco/js-api';
})
export class BpmUserService {
private profileApi: UserProfileApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.profileApi = new UserProfileApi(this.apiService.getInstance());
}
/**
@@ -42,7 +45,7 @@ export class BpmUserService {
* @returns User information object
*/
getCurrentUserInfo(): Observable<BpmUserModel> {
return from(this.apiService.getInstance().activiti.profileApi.getProfile())
return from(this.profileApi.getProfile())
.pipe(
map((userRepresentation: UserRepresentation) => {
return new BpmUserModel(userRepresentation);
@@ -56,7 +59,7 @@ export class BpmUserService {
* @returns URL string
*/
getCurrentUserProfileImage(): string {
return this.apiService.getInstance().activiti.profileApi.getProfilePictureUrl();
return this.profileApi.getProfilePictureUrl();
}
/**

View File

@@ -21,15 +21,18 @@ import { CommentModel } from '../models/comment.model';
import { AlfrescoApiService } from '../services/alfresco-api.service';
import { LogService } from '../services/log.service';
import { map, catchError } from 'rxjs/operators';
import { CommentEntry } from '@alfresco/js-api';
import { CommentEntry, CommentsApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
})
export class CommentContentService {
private commentsApi: CommentsApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.commentsApi = new CommentsApi(this.apiService.getInstance());
}
/**
@@ -39,7 +42,7 @@ export class CommentContentService {
* @returns Details of the comment added
*/
addNodeComment(nodeId: string, message: string): Observable<CommentModel> {
return from(this.apiService.getInstance().core.commentsApi.addComment(nodeId, {content: message}))
return from(this.commentsApi.createComment(nodeId, {content: message}))
.pipe(
map((response: CommentEntry) => {
return new CommentModel({
@@ -59,7 +62,7 @@ export class CommentContentService {
* @returns Details for each comment
*/
getNodeComments(nodeId: string): Observable<CommentModel[]> {
return from(this.apiService.getInstance().core.commentsApi.getComments(nodeId))
return from(this.commentsApi.listComments(nodeId))
.pipe(
map((response) => {
const comments: CommentModel[] = [];

View File

@@ -20,7 +20,6 @@ import { CommentModel } from '../models/comment.model';
import { fakeProcessComment, fakeTasksComment, fakeUser1 } from '../mock/comment-process-service.mock';
import { CommentProcessService } from './comment-process.service';
import { setupTestBed } from '../testing/setup-test-bed';
import { AlfrescoApiService } from './alfresco-api.service';
import { CoreTestingModule } from '../testing/core.testing.module';
import { TranslateModule } from '@ngx-translate/core';
@@ -29,7 +28,6 @@ declare let jasmine: any;
describe('Comment ProcessService Service', () => {
let service: CommentProcessService;
let alfrescoApi: any;
setupTestBed({
imports: [
@@ -40,7 +38,6 @@ describe('Comment ProcessService Service', () => {
beforeEach(() => {
service = TestBed.inject(CommentProcessService);
alfrescoApi = TestBed.inject(AlfrescoApiService).getInstance();
});
beforeEach(() => {
@@ -60,7 +57,7 @@ describe('Comment ProcessService Service', () => {
let getProcessInstanceComments: jasmine.Spy;
beforeEach(() => {
getProcessInstanceComments = spyOn(alfrescoApi.activiti.commentsApi, 'getProcessInstanceComments')
getProcessInstanceComments = spyOn(service['commentsApi'], 'getProcessInstanceComments')
.and
.returnValue(Promise.resolve({data: [fakeProcessComment, fakeProcessComment]}));
});
@@ -108,7 +105,7 @@ describe('Comment ProcessService Service', () => {
let addProcessInstanceComment: jasmine.Spy;
beforeEach(() => {
addProcessInstanceComment = spyOn(alfrescoApi.activiti.commentsApi, 'addProcessInstanceComment')
addProcessInstanceComment = spyOn(service['commentsApi'], 'addProcessInstanceComment')
.and
.returnValue(Promise.resolve(fakeProcessComment));
});

View File

@@ -22,14 +22,18 @@ import { UserProcessModel } from '../models/user-process.model';
import { AlfrescoApiService } from './alfresco-api.service';
import { LogService } from './log.service';
import { map, catchError } from 'rxjs/operators';
import { ActivitiCommentsApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
})
export class CommentProcessService {
private commentsApi: ActivitiCommentsApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.commentsApi = new ActivitiCommentsApi(this.apiService.getInstance());
}
/**
@@ -39,7 +43,7 @@ export class CommentProcessService {
* @returns Details about the comment
*/
addTaskComment(taskId: string, message: string): Observable<CommentModel> {
return from(this.apiService.getInstance().activiti.taskApi.addTaskComment({ message: message }, taskId))
return from(this.commentsApi.addTaskComment({ message: message }, taskId))
.pipe(
map((response) => {
return new CommentModel({
@@ -59,7 +63,7 @@ export class CommentProcessService {
* @returns Details for each comment
*/
getTaskComments(taskId: string): Observable<CommentModel[]> {
return from(this.apiService.getInstance().activiti.taskApi.getTaskComments(taskId))
return from(this.commentsApi.getTaskComments(taskId))
.pipe(
map((response) => {
const comments: CommentModel[] = [];
@@ -84,7 +88,7 @@ export class CommentProcessService {
* @returns Details for each comment
*/
getProcessInstanceComments(processInstanceId: string): Observable<CommentModel[]> {
return from(this.apiService.getInstance().activiti.commentsApi.getProcessInstanceComments(processInstanceId))
return from(this.commentsApi.getProcessInstanceComments(processInstanceId))
.pipe(
map((response) => {
const comments: CommentModel[] = [];
@@ -111,7 +115,7 @@ export class CommentProcessService {
*/
addProcessInstanceComment(processInstanceId: string, message: string): Observable<CommentModel> {
return from(
this.apiService.getInstance().activiti.commentsApi.addProcessInstanceComment({ message: message }, processInstanceId)
this.commentsApi.addProcessInstanceComment({ message: message }, processInstanceId)
).pipe(
map((response) => {
return new CommentModel({

View File

@@ -17,7 +17,7 @@
import { Injectable } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { ContentApi, MinimalNode, Node, NodeEntry } from '@alfresco/js-api';
import { ContentApi, MinimalNode, Node, NodeEntry, NodesApi } from '@alfresco/js-api';
import { Observable, Subject, from, throwError } from 'rxjs';
import { FolderCreatedEvent } from '../events/folder-created.event';
import { AlfrescoApiService } from './alfresco-api.service';
@@ -38,12 +38,17 @@ export class ContentService {
folderCreate: Subject<MinimalNode> = new Subject<MinimalNode>();
folderEdit: Subject<MinimalNode> = new Subject<MinimalNode>();
private contentApi: ContentApi;
private nodesApi: NodesApi;
constructor(public authService: AuthenticationService,
public apiService: AlfrescoApiService,
private logService: LogService,
private sanitizer: DomSanitizer,
private downloadService: DownloadService,
private thumbnailService: ThumbnailService) {
this.contentApi = new ContentApi(apiService.getInstance());
this.nodesApi = new NodesApi(apiService.getInstance());
}
/**
@@ -56,26 +61,6 @@ export class ContentService {
this.downloadService.downloadBlob(blob, fileName);
}
/**
* @deprecated in 3.2.0, use DownloadService instead.
* Invokes content download for a data array with a file name.
* @param data Data to download.
* @param fileName Name of the resulting file.
*/
downloadData(data: any, fileName: string): void {
this.downloadService.downloadData(data, fileName);
}
/**
* @deprecated in 3.2.0, use DownloadService instead.
* Invokes content download for a JSON object with a file name.
* @param json JSON object to download.
* @param fileName Name of the resulting file.
*/
downloadJSON(json: any, fileName: string): void {
this.downloadService.downloadJSON(json, fileName);
}
/**
* Creates a trusted object URL from the Blob.
* WARNING: calling this method with untrusted user data exposes your application to XSS security risks!
@@ -87,10 +72,6 @@ export class ContentService {
return <string> this.sanitizer.bypassSecurityTrustUrl(url);
}
private get contentApi(): ContentApi {
return this.apiService.getInstance().content;
}
/**
* @deprecated in 3.2.0, use ThumbnailService instead.
* Gets a thumbnail URL for the given document node.
@@ -132,7 +113,7 @@ export class ContentService {
* @returns Content data
*/
getNodeContent(nodeId: string): Observable<any> {
return from(this.apiService.getInstance().core.nodesApi.getFileContent(nodeId))
return from(this.nodesApi.getNodeContent(nodeId))
.pipe(
catchError((err: any) => this.handleError(err))
);
@@ -145,7 +126,7 @@ export class ContentService {
* @returns Details of the folder
*/
getNode(nodeId: string, opts?: any): Observable<NodeEntry> {
return from(this.apiService.getInstance().nodes.getNode(nodeId, opts));
return from(this.nodesApi.getNode(nodeId, opts));
}
/**
@@ -159,13 +140,13 @@ export class ContentService {
let hasPermissions = false;
userId = userId ?? this.authService.getEcmUsername();
const permissions = [ ...(node.permissions?.locallySet || []), ...(node.permissions?.inherited || []) ]
.filter((currentPermission) => currentPermission.authorityId === userId);
const permissions = [...(node.permissions?.locallySet || []), ...(node.permissions?.inherited || [])]
.filter((currentPermission) => currentPermission.authorityId === userId);
if (permissions.length) {
if (permission && permission.startsWith('!')) {
hasPermissions = permissions.find((currentPermission) => currentPermission.name === permission.replace('!', '')) ? false : true;
hasPermissions = !permissions.find((currentPermission) => currentPermission.name === permission.replace('!', ''));
} else {
hasPermissions = permissions.find((currentPermission) => currentPermission.name === permission) ? true : false;
hasPermissions = !!permissions.find((currentPermission) => currentPermission.name === permission);
}
} else {
@@ -193,9 +174,9 @@ export class ContentService {
if (node && node.allowableOperations) {
if (allowableOperation && allowableOperation.startsWith('!')) {
hasAllowableOperations = node.allowableOperations.find((currentOperation) => currentOperation === allowableOperation.replace('!', '')) ? false : true;
hasAllowableOperations = !node.allowableOperations.find((currentOperation) => currentOperation === allowableOperation.replace('!', ''));
} else {
hasAllowableOperations = node.allowableOperations.find((currentOperation) => currentOperation === allowableOperation) ? true : false;
hasAllowableOperations = !!node.allowableOperations.find((currentOperation) => currentOperation === allowableOperation);
}
} else {

View File

@@ -18,7 +18,7 @@
import { Injectable } from '@angular/core';
import { Observable, from, of } from 'rxjs';
import { NodePaging } from '@alfresco/js-api';
import { NodePaging, NodesApi, TrashcanApi } from '@alfresco/js-api';
import { AlfrescoApiService } from './alfresco-api.service';
import { UserPreferencesService } from './user-preferences.service';
import { catchError } from 'rxjs/operators';
@@ -27,13 +27,16 @@ import { catchError } from 'rxjs/operators';
providedIn: 'root'
})
export class DeletedNodesApiService {
nodesApi: NodesApi;
trashcanApi: TrashcanApi;
constructor(
private apiService: AlfrescoApiService,
private preferences: UserPreferencesService
) {}
private get nodesApi() {
return this.apiService.getInstance().core.nodesApi;
) {
this.nodesApi = new NodesApi(this.apiService.getInstance());
this.trashcanApi = new TrashcanApi(this.apiService.getInstance());
}
/**
@@ -48,7 +51,7 @@ export class DeletedNodesApiService {
skipCount: 0
};
const queryOptions = Object.assign(defaultOptions, options);
const promise = this.nodesApi.getDeletedNodes(queryOptions);
const promise = this.trashcanApi.listDeletedNodes(queryOptions);
return from(promise).pipe(
catchError((err) => of(err))

View File

@@ -1,258 +0,0 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TestBed } from '@angular/core/testing';
import { BpmProductVersionModel, EcmProductVersionModel } from '../models/product-version.model';
import { DiscoveryApiService } from './discovery-api.service';
import { AlfrescoApiService } from './alfresco-api.service';
import { AuthenticationService } from './authentication.service';
import { setupTestBed } from '../testing/setup-test-bed';
import { CoreTestingModule } from '../testing/core.testing.module';
import { DiscoveryEntry, SystemPropertiesRepresentation } from '@alfresco/js-api';
import { TranslateModule } from '@ngx-translate/core';
import { of } from 'rxjs';
const fakeEcmDiscoveryResponse = new DiscoveryEntry({
entry: {
repository: {
edition: 'FAKE',
version: {
major: '5',
minor: '2',
patch: '0',
hotfix: '0',
schema: 999999,
label: 'r134899-b26',
display: '5.2.0.0 (r134899-b26) schema 10005'
},
license: {
issuedAt: '2017-06-22T10:56:45.796+0000',
expiresAt: '2017-07-22T00:00:00.000+0000',
remainingDays: 4,
holder: 'Trial User',
mode: 'ENTERPRISE',
entitlements: {
isClusterEnabled: false,
isCryptodocEnabled: false
}
},
status: {
isReadOnly: false,
isAuditEnabled: true,
isQuickShareEnabled: true,
isThumbnailGenerationEnabled: true
},
modules: [
{
id: 'alfresco-fake-services',
title: 'Alfresco Share Services AMP',
description: 'Module to be applied to alfresco.war, containing APIs for Alfresco Share',
version: '5.2.0',
installDate: '2017-03-07T08:48:14.161+0000',
installState: 'INSTALLED',
versionMin: '5.1',
versionMax: '999'
},
{
id: 'alfresco-trashcan-fake',
title: 'alfresco-trashcan-cleaner project',
description: 'The Alfresco Trash Can Cleaner (Alfresco Module)',
version: '2.2',
installState: 'UNKNOWN',
versionMin: '0',
versionMax: '999'
}
]
}
}
});
const fakeBPMDiscoveryResponse: any = {
revisionVersion: '2',
edition: 'SUPER FAKE EDITION',
type: 'bpmSuite',
majorVersion: '1',
minorVersion: '6'
};
const fakeBPMDiscoverySystemPropertyResponse = new SystemPropertiesRepresentation({
allowInvolveByEmail: true,
disableJavaScriptEventsInFormEditor: false,
logoutDisabled: false,
authConfiguration: {
authUrl: 'fakeAuthUrl',
realm: 'fakeRealm',
clientId: 'fakeClient',
useBrowserLogout: true
}
});
describe('Discovery Api Service', () => {
let service: DiscoveryApiService;
let apiService: AlfrescoApiService;
let authenticationService: AuthenticationService;
describe('Basic auth', () => {
setupTestBed({
imports: [TranslateModule.forRoot(), CoreTestingModule]
});
beforeEach(() => {
service = TestBed.inject(DiscoveryApiService);
apiService = TestBed.inject(AlfrescoApiService);
});
describe('For ECM', () => {
it('Should retrieve the info about the product for ECM', done => {
spyOn(apiService.getInstance().discovery.discoveryApi, 'getRepositoryInformation')
.and.returnValue(Promise.resolve(fakeEcmDiscoveryResponse));
service.getEcmProductInfo()
.subscribe((data: EcmProductVersionModel) => {
expect(data).not.toBeNull();
expect(data.edition).toBe('FAKE');
expect(data.version.schema).toBe(999999);
expect(data.license.isClusterEnabled).toBeFalsy();
expect(data.status.isQuickShareEnabled).toBeTruthy();
expect(data.modules.length).toBe(2);
expect(data.modules[0].id).toBe('alfresco-fake-services');
expect(data.modules[1].id).toBe('alfresco-trashcan-fake');
done();
});
});
it('getEcmProductInfo catch errors call', done => {
spyOn(apiService.getInstance().discovery.discoveryApi, 'getRepositoryInformation')
.and.returnValue(Promise.reject({ status: 403 }));
service.getEcmProductInfo().subscribe(
() => {},
() => {
done();
}
);
});
});
describe('For BPM', () => {
it('Should retrieve the info about the product for BPM', done => {
spyOn(apiService.getInstance().activiti.aboutApi, 'getAppVersion')
.and.returnValue(Promise.resolve(fakeBPMDiscoveryResponse));
service.getBpmProductInfo().subscribe((data: BpmProductVersionModel) => {
expect(data).not.toBeNull();
expect(data.edition).toBe('SUPER FAKE EDITION');
expect(data.revisionVersion).toBe('2');
expect(data.type).toBe('bpmSuite');
done();
});
});
it('getBpmProductInfo catch errors call', done => {
spyOn(apiService.getInstance().activiti.aboutApi, 'getAppVersion')
.and.returnValue(Promise.reject({ status: 403 }));
service.getBpmProductInfo().subscribe(
() => {},
() => {
done();
}
);
});
it('Should retrieve the system properties for BPM', done => {
spyOn(apiService.getInstance().activiti.systemPropertiesApi, 'getProperties')
.and.returnValue(Promise.resolve(fakeBPMDiscoverySystemPropertyResponse));
service.getBPMSystemProperties().subscribe((data: SystemPropertiesRepresentation) => {
expect(data).not.toBeNull();
expect(data.allowInvolveByEmail).toBe(true);
expect(data.disableJavaScriptEventsInFormEditor).toBe(false);
expect(data.logoutDisabled).toBe(false);
expect(data.authConfiguration.authUrl).toBe('fakeAuthUrl');
expect(data.authConfiguration.realm).toBe('fakeRealm');
expect(data.authConfiguration.clientId).toBe('fakeClient');
expect(data.authConfiguration.useBrowserLogout).toBe(true);
done();
});
});
it('Should retrieve the system properties for BPM', done => {
spyOn(
apiService.getInstance().activiti.systemPropertiesApi,
'getProperties'
).and.returnValue(
Promise.reject({
error: {
response: {
statusCode: 404,
statusText: 'Not Found'
}
}
})
);
service.getBPMSystemProperties().subscribe(
() => {
fail('expected an error, bpm not running');
},
error => {
expect(error.response.statusCode).toEqual(404);
expect(error.response.statusText).toEqual('Not Found');
done();
}
);
});
});
});
describe('OnLogin Event', () => {
setupTestBed({
imports: [
TranslateModule.forRoot(),
CoreTestingModule
]
});
beforeEach(() => {
service = TestBed.inject(DiscoveryApiService);
apiService = TestBed.inject(AlfrescoApiService);
authenticationService = TestBed.inject(AuthenticationService);
});
it('Should retrieve the info about the product on login/refresh the application', done => {
spyOn(apiService.getInstance(), 'isEcmLoggedIn').and.returnValue(true);
spyOn(service, 'getEcmProductInfo').and.returnValue(of(new EcmProductVersionModel(fakeEcmDiscoveryResponse)));
const subscription = service.ecmProductInfo$.subscribe(
(data: EcmProductVersionModel) => {
expect(data).not.toBeNull();
expect(data.edition).toBe('FAKE');
expect(data.version.schema).toBe(999999);
expect(data.license.isClusterEnabled).toBeFalsy();
expect(data.status.isQuickShareEnabled).toBeTruthy();
expect(data.modules.length).toBe(2);
expect(data.modules[0].id).toBe('alfresco-fake-services');
expect(data.modules[1].id).toBe('alfresco-trashcan-fake');
subscription.unsubscribe();
done();
}
);
authenticationService.onLogin.next('<token>');
});
});
});

View File

@@ -20,7 +20,7 @@ import { from, Observable, throwError, Subject } from 'rxjs';
import { BpmProductVersionModel, EcmProductVersionModel } from '../models/product-version.model';
import { AlfrescoApiService } from './alfresco-api.service';
import { catchError, map, switchMap, filter, take } from 'rxjs/operators';
import { Activiti, SystemPropertiesRepresentation } from '@alfresco/js-api';
import { AboutApi, DiscoveryApi, SystemPropertiesApi, SystemPropertiesRepresentation } from '@alfresco/js-api';
import { AuthenticationService } from './authentication.service';
@Injectable({
@@ -51,7 +51,9 @@ export class DiscoveryApiService {
* @returns ProductVersionModel containing product details
*/
public getEcmProductInfo(): Observable<EcmProductVersionModel> {
return from(this.apiService.getInstance().discovery.discoveryApi.getRepositoryInformation())
const discoveryApi = new DiscoveryApi(this.apiService.getInstance());
return from(discoveryApi.getRepositoryInformation())
.pipe(
map((res) => new EcmProductVersionModel(res)),
catchError((err) => throwError(err))
@@ -63,19 +65,19 @@ export class DiscoveryApiService {
* @returns ProductVersionModel containing product details
*/
public getBpmProductInfo(): Observable<BpmProductVersionModel> {
return from(this.apiService.getInstance().activiti.aboutApi.getAppVersion())
const aboutApi = new AboutApi(this.apiService.getInstance());
return from(aboutApi.getAppVersion())
.pipe(
map((res) => new BpmProductVersionModel(res)),
catchError((err) => throwError(err))
);
}
private get systemPropertiesApi(): Activiti.SystemPropertiesApi {
return this.apiService.getInstance().activiti.systemPropertiesApi;
}
public getBPMSystemProperties(): Observable<SystemPropertiesRepresentation> {
return from(this.systemPropertiesApi.getProperties())
const systemPropertiesApi = new SystemPropertiesApi(this.apiService.getInstance());
return from(systemPropertiesApi.getProperties())
.pipe(
map((res) => {
if ('string' === typeof (res)) {

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { NodeEntry, DownloadEntry, DownloadBodyCreate } from '@alfresco/js-api';
import { DownloadEntry, DownloadBodyCreate, DownloadsApi } from '@alfresco/js-api';
import { Injectable } from '@angular/core';
import { Observable, from, throwError } from 'rxjs';
import { LogService } from './log.service';
@@ -27,8 +27,11 @@ import { catchError } from 'rxjs/operators';
})
export class DownloadZipService {
downloadsApi: DownloadsApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.downloadsApi = new DownloadsApi(this.apiService.getInstance());
}
/**
@@ -37,37 +40,18 @@ export class DownloadZipService {
* @returns Status object for the download
*/
createDownload(payload: DownloadBodyCreate): Observable<DownloadEntry> {
return from(this.apiService.getInstance().core.downloadsApi.createDownload(payload)).pipe(
return from(this.downloadsApi.createDownload(payload)).pipe(
catchError((err) => this.handleError(err))
);
}
/**
* Gets a content URL for the given node.
* @param nodeId Node to get URL for.
* @param attachment Toggles whether to retrieve content as an attachment for download
* @returns URL string
*/
getContentUrl(nodeId: string, attachment?: boolean): string {
return this.apiService.getInstance().content.getContentUrl(nodeId, attachment);
}
/**
* Gets a Node via its node ID.
* @param nodeId ID of the target node
* @returns Details of the node
*/
getNode(nodeId: string): Observable<NodeEntry> {
return from(this.apiService.getInstance().core.nodesApi.getNode(nodeId));
}
/**
* Gets status information for a download node.
* @param downloadId ID of the download node
* @returns Status object for the download
*/
getDownload(downloadId: string): Observable<DownloadEntry> {
return from(this.apiService.getInstance().core.downloadsApi.getDownload(downloadId));
return from(this.downloadsApi.getDownload(downloadId));
}
/**
@@ -75,7 +59,7 @@ export class DownloadZipService {
* @param downloadId ID of the target download node
*/
cancelDownload(downloadId: string) {
this.apiService.getInstance().core.downloadsApi.cancelDownload(downloadId);
this.downloadsApi.cancelDownload(downloadId);
}
private handleError(error: any) {

View File

@@ -16,7 +16,7 @@
*/
import { Injectable } from '@angular/core';
import { NodePaging } from '@alfresco/js-api';
import { FavoritesApi, NodePaging, FavoritePaging } from '@alfresco/js-api';
import { Observable, from, of } from 'rxjs';
import { AlfrescoApiService } from './alfresco-api.service';
import { UserPreferencesService } from './user-preferences.service';
@@ -27,6 +27,8 @@ import { catchError } from 'rxjs/operators';
})
export class FavoritesApiService {
private favoritesApi: FavoritesApi;
static remapEntry({ entry }: any): any {
entry.properties = {
'cm:title': entry.title,
@@ -36,11 +38,17 @@ export class FavoritesApiService {
return { entry };
}
remapFavoritesData(data: any = {}): NodePaging {
const list = (data.list || {});
const pagination = (list.pagination || {});
constructor(
private apiService: AlfrescoApiService,
private preferences: UserPreferencesService
) {
this.favoritesApi = new FavoritesApi(this.apiService.getInstance());
}
remapFavoritesData(data: FavoritePaging = {}): NodePaging {
const pagination = (data?.list?.pagination || {});
const entries: any[] = this
.remapFavoriteEntries(list.entries || []);
.remapFavoriteEntries(data?.list?.entries || []);
return <NodePaging> {
list: { entries, pagination }
@@ -49,22 +57,13 @@ export class FavoritesApiService {
remapFavoriteEntries(entries: any[]) {
return entries
.map(({ entry: { target }}: any) => ({
.map(({ entry: { target } }: any) => ({
entry: target.file || target.folder
}))
.filter(({ entry }) => (!!entry))
.map(FavoritesApiService.remapEntry);
}
constructor(
private apiService: AlfrescoApiService,
private preferences: UserPreferencesService
) {}
private get favoritesApi() {
return this.apiService.getInstance().core.favoritesApi;
}
/**
* Gets the favorites for a user.
* @param personId ID of the user
@@ -76,11 +75,11 @@ export class FavoritesApiService {
maxItems: this.preferences.paginationSize,
skipCount: 0,
where: '(EXISTS(target/file) OR EXISTS(target/folder))',
include: [ 'properties', 'allowableOperations' ]
include: ['properties', 'allowableOperations']
};
const queryOptions = Object.assign(defaultOptions, options);
const promise = this.favoritesApi
.getFavorites(personId, queryOptions)
.listFavorites(personId, queryOptions)
.then(this.remapFavoritesData);
return from(promise).pipe(

View File

@@ -33,10 +33,7 @@ export class LockService {
let isLocked = false;
if (this.hasLockConfigured(node)) {
if (this.isReadOnlyLock(node)) {
isLocked = true;
if (this.isLockExpired(node)) {
isLocked = false;
}
isLocked = !this.isLockExpired(node);
} else if (this.isLockOwnerAllowed(node)) {
isLocked = this.alfrescoApiService.getInstance().getEcmUsername() !== node.properties['cm:lockOwner'].id;
if (this.isLockExpired(node)) {

View File

@@ -1,164 +0,0 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TestBed } from '@angular/core/testing';
import { NodesApiService } from './nodes-api.service';
import { setupTestBed } from '../testing/setup-test-bed';
import { AlfrescoApiService } from './alfresco-api.service';
import { NodeMetadata } from '../models/node-metadata.model';
import { CoreTestingModule } from '../testing/core.testing.module';
import { TranslateModule } from '@ngx-translate/core';
describe('NodesApiService', () => {
let service: NodesApiService;
let apiService: AlfrescoApiService;
const MODEL_NAMESPACE = 'activitiForms';
const responseBody = {
entry: {
id: '111-222-33-44-1123',
nodeType: 'typeTest',
properties: {
test: 'test',
testdata: 'testdata'
}
}
};
const mockSpy: any = {
core: {
nodesApi: {
getNode: jasmine.createSpy('getNode'),
getNodeChildren: jasmine.createSpy('getNodeChildren'),
addNode: jasmine.createSpy('addNode')
}
},
isEcmLoggedIn() {
return false;
},
reply: jasmine.createSpy('reply')
};
setupTestBed({
imports: [
TranslateModule.forRoot(),
CoreTestingModule
]
});
beforeEach(() => {
service = TestBed.inject(NodesApiService);
apiService = TestBed.inject(AlfrescoApiService);
spyOn(apiService, 'getInstance').and.returnValue(mockSpy);
});
afterEach(() => {
mockSpy.core.nodesApi.getNode.calls.reset();
mockSpy.core.nodesApi.getNodeChildren.calls.reset();
mockSpy.core.nodesApi.addNode.calls.reset();
});
it('Should return the node information', (done) => {
mockSpy.core.nodesApi.getNode.and.returnValue(Promise.resolve(responseBody));
service.getNode('-nodeid-').subscribe((result) => {
const args = [
'-nodeid-',
{ 'include': ['path', 'properties', 'allowableOperations', 'permissions'] }
];
expect(mockSpy.core.nodesApi.getNode.calls.mostRecent().args).toEqual(args);
expect(result).toEqual(<any> responseBody.entry);
done();
});
});
it('Should return the node child information', (done) => {
const fakeNodeList = {
list: {
entries: [
{ entry: { id: 'fake-node-id', name: 'fake-node-name', isFolder: true } },
{ entry: { id: 'fake-file-id', name: 'fake-file-name', isFolder: false } }
]
}
};
mockSpy.core.nodesApi.getNodeChildren.and.returnValue(Promise.resolve(fakeNodeList));
service.getNodeChildren('-nodeid-', {}).subscribe((result) => {
const args = [
'-nodeid-',
{
'include': ['path', 'properties', 'allowableOperations', 'permissions'],
maxItems: 25,
skipCount: 0
}
];
expect(mockSpy.core.nodesApi.getNodeChildren.calls.mostRecent().args).toEqual(args);
expect(result).toBe(<any> fakeNodeList);
done();
});
});
it('Should fetch and node metadata', (done) => {
mockSpy.core.nodesApi.getNode.and.returnValue(Promise.resolve(responseBody));
service.getNodeMetadata('-nodeid-').subscribe((result) => {
const node = new NodeMetadata({
test: 'test',
testdata: 'testdata'
}, 'typeTest');
expect(result).toEqual(node);
done();
});
});
it('Should create a node with metadata', (done) => {
const data = {
test: 'test',
testdata: 'testdata'
};
mockSpy.core.nodesApi.addNode.and.returnValue(Promise.resolve(responseBody));
service.createNodeMetadata('typeTest', MODEL_NAMESPACE, data, '/Sites/swsdp/documentLibrary', 'testNode').subscribe((response) => {
const args = [
'-root-',
{
'name': 'testNode',
'nodeType': 'typeTest',
'properties': {
'activitiForms:test': 'test',
'activitiForms:testdata': 'testdata'
},
'relativePath': '/Sites/swsdp/documentLibrary'
},
{}
];
expect(mockSpy.core.nodesApi.addNode.calls.mostRecent().args).toEqual(args);
expect(response).toBe(<any> responseBody);
done();
});
});
it('Should create a random name node with metadata', (done) => {
const uuidRegex = /[0-9a-z]{8}-[0-9a-z]{4}-4[0-9a-z]{3}-[0-9a-z]{4}-[0-9a-z]{12}/;
mockSpy.core.nodesApi.addNode.and.returnValue(Promise.resolve(responseBody));
service.createNodeMetadata('typeTest', MODEL_NAMESPACE, {}, '/Sites/swsdp/documentLibrary').subscribe(() => {
expect(mockSpy.core.nodesApi.addNode.calls.mostRecent().args[0]).toEqual('-root-');
expect(uuidRegex.test(mockSpy.core.nodesApi.addNode.calls.mostRecent().args[1].name)).toBe(true);
done();
});
});
});

View File

@@ -16,7 +16,7 @@
*/
import { Injectable } from '@angular/core';
import { MinimalNode, NodeEntry, NodePaging } from '@alfresco/js-api';
import { MinimalNode, NodeEntry, NodePaging, NodesApi, TrashcanApi } from '@alfresco/js-api';
import { from, Observable, throwError } from 'rxjs';
import { AlfrescoApiService } from './alfresco-api.service';
import { UserPreferencesService } from './user-preferences.service';
@@ -28,11 +28,13 @@ import { NodeMetadata } from '../models/node-metadata.model';
})
export class NodesApiService {
constructor(private api: AlfrescoApiService,
private preferences: UserPreferencesService) {}
private nodesApi: NodesApi;
private trashcanApi: TrashcanApi;
private get nodesApi() {
return this.api.getInstance().core.nodesApi;
constructor(private apiService: AlfrescoApiService,
private preferences: UserPreferencesService) {
this.nodesApi = new NodesApi(this.apiService.getInstance());
this.trashcanApi = new TrashcanApi(this.apiService.getInstance());
}
private getEntryFromEntity(entity: NodeEntry) {
@@ -47,7 +49,7 @@ export class NodesApiService {
*/
getNode(nodeId: string, options: any = {}): Observable<MinimalNode> {
const defaults = {
include: [ 'path', 'properties', 'allowableOperations', 'permissions' ]
include: ['path', 'properties', 'allowableOperations', 'permissions']
};
const queryOptions = Object.assign(defaults, options);
@@ -67,11 +69,11 @@ export class NodesApiService {
const defaults = {
maxItems: this.preferences.paginationSize,
skipCount: 0,
include: [ 'path', 'properties', 'allowableOperations', 'permissions' ]
include: ['path', 'properties', 'allowableOperations', 'permissions']
};
const queryOptions = Object.assign(defaults, options);
return from(this.nodesApi.getNodeChildren(nodeId, queryOptions)).pipe(
return from(this.nodesApi.listNodeChildren(nodeId, queryOptions)).pipe(
catchError((err) => throwError(err))
);
}
@@ -84,7 +86,7 @@ export class NodesApiService {
* @returns Details of the new node
*/
createNode(parentNodeId: string, nodeBody: any, options: any = {}): Observable<MinimalNode> {
return from(this.nodesApi.addNode(parentNodeId, nodeBody, options)).pipe(
return from(this.nodesApi.createNode(parentNodeId, nodeBody, options)).pipe(
map(this.getEntryFromEntity),
catchError((err) => throwError(err))
);
@@ -111,12 +113,12 @@ export class NodesApiService {
*/
updateNode(nodeId: string, nodeBody: any, options: any = {}): Observable<MinimalNode> {
const defaults = {
include: [ 'path', 'properties', 'allowableOperations', 'permissions', 'definition' ]
include: ['path', 'properties', 'allowableOperations', 'permissions', 'definition']
};
const queryOptions = Object.assign(defaults, options);
return from(this.nodesApi.updateNode(nodeId, nodeBody, queryOptions)).pipe(
map(this.getEntryFromEntity),
map(this.getEntryFromEntity),
catchError((err) => throwError(err))
);
}
@@ -139,7 +141,7 @@ export class NodesApiService {
* @returns Details of the restored node
*/
restoreNode(nodeId: string): Observable<MinimalNode> {
return from(this.nodesApi.restoreNode(nodeId)).pipe(
return from(this.trashcanApi.restoreDeletedNode(nodeId)).pipe(
map(this.getEntryFromEntity),
catchError((err) => throwError(err))
);
@@ -190,7 +192,7 @@ export class NodesApiService {
properties: properties,
relativePath: path
};
return from(this.nodesApi.addNode('-root-', body, {}));
return from(this.nodesApi.createNode('-root-', body, {}));
}
private generateUuid() {

View File

@@ -1,96 +0,0 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TestBed } from '@angular/core/testing';
import { setupTestBed } from '../testing/setup-test-bed';
import { AppConfigService } from '../app-config/app-config.service';
import { PageTitleService } from './page-title.service';
import { TranslationService } from './translation.service';
import { Title } from '@angular/platform-browser';
import { CoreModule } from '../core.module';
import { TranslateModule } from '@ngx-translate/core';
describe('PageTitleService', () => {
let titleService: Title;
let translationService: TranslationService;
let pageTitleService: PageTitleService;
let appConfigService: AppConfigService;
let titleServiceSpy: jasmine.Spy;
setupTestBed({
imports: [
TranslateModule.forRoot(),
CoreModule.forRoot()
]
});
beforeEach(() => {
titleService = TestBed.inject(Title);
pageTitleService = TestBed.inject(PageTitleService);
translationService = TestBed.inject(TranslationService);
appConfigService = TestBed.inject(AppConfigService);
titleServiceSpy = spyOn(titleService, 'setTitle').and.callThrough();
appConfigService.config.application.name = 'My application';
});
it('should set default application name', () => {
appConfigService.config.application = {};
pageTitleService.setTitle();
expect(titleServiceSpy).toHaveBeenCalledWith('Alfresco ADF Application');
});
it('should set only the application name', () => {
pageTitleService.setTitle();
expect(titleServiceSpy).toHaveBeenCalledWith('My application');
});
it('should append application name to the title', () => {
pageTitleService.setTitle('My page');
expect(titleServiceSpy).toHaveBeenCalledWith('My page - My application');
});
it('should update title on language change', () => {
// cspell: disable-next
spyOn(translationService, 'instant').and.returnValues('hello', 'привет');
pageTitleService.setTitle('key');
expect(titleServiceSpy).toHaveBeenCalledWith('hello - My application');
(<any> titleService).setTitle.calls.reset();
translationService.translate.onLangChange.next(<any> {});
// cspell: disable-next
expect(titleServiceSpy).toHaveBeenCalledWith('привет - My application');
});
it('should update title on new content download', () => {
// cspell: disable-next
spyOn(translationService, 'instant').and.returnValues('hello', 'привет');
pageTitleService.setTitle('key');
expect(titleServiceSpy).toHaveBeenCalledWith('hello - My application');
(<any> titleService).setTitle.calls.reset();
translationService.translate.onTranslationChange.next(<any> {});
// cspell: disable-next
expect(titleServiceSpy).toHaveBeenCalledWith('привет - My application');
});
});

View File

@@ -47,7 +47,7 @@ describe('PeopleContentService', () => {
});
it('should be able to fetch person details based on id', (done) => {
spyOn(service.peopleApi, 'getPerson').and.returnValue(Promise.resolve(new PersonEntry({ entry: fakeEcmUser })));
spyOn(service['peopleApi'], 'getPerson').and.returnValue(Promise.resolve(new PersonEntry({ entry: fakeEcmUser })));
service.getPerson('fake-id').subscribe((person) => {
expect(person.entry.id).toEqual('fake-id');
expect(person.entry.email).toEqual('fakeEcm@ecmUser.com');
@@ -56,7 +56,7 @@ describe('PeopleContentService', () => {
});
it('calls getPerson api method by an id', (done) => {
const getPersonSpy = spyOn(service.peopleApi, 'getPerson').and.returnValue(Promise.resolve(null));
const getPersonSpy = spyOn(service['peopleApi'], 'getPerson').and.returnValue(Promise.resolve(null));
service.getPerson('fake-id').subscribe(() => {
expect(getPersonSpy).toHaveBeenCalledWith('fake-id');
done();
@@ -64,7 +64,7 @@ describe('PeopleContentService', () => {
});
it('calls getPerson api method with "-me-"', (done) => {
const getPersonSpy = spyOn(service.peopleApi, 'getPerson').and.returnValue(Promise.resolve(null));
const getPersonSpy = spyOn(service['peopleApi'], 'getPerson').and.returnValue(Promise.resolve(null));
service.getPerson('-me-').subscribe(() => {
expect(getPersonSpy).toHaveBeenCalledWith('-me-');
done();
@@ -72,7 +72,7 @@ describe('PeopleContentService', () => {
});
it('should be able to list people', (done) => {
spyOn(service.peopleApi, 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
spyOn(service['peopleApi'], 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
service.listPeople().subscribe((response: PeopleContentQueryResponse) => {
const people = response.entries, pagination = response.pagination;
expect(people).toBeDefined();
@@ -87,7 +87,7 @@ describe('PeopleContentService', () => {
});
it('should call listPeople api method', (done) => {
const listPeopleSpy = spyOn(service.peopleApi, 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
const listPeopleSpy = spyOn(service['peopleApi'], 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
service.listPeople().subscribe(() => {
expect(listPeopleSpy).toHaveBeenCalled();
done();
@@ -95,7 +95,7 @@ describe('PeopleContentService', () => {
});
it('should call listPeople api with requested sorting params', async () => {
const listPeopleSpy = spyOn(service.peopleApi, 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
const listPeopleSpy = spyOn(service['peopleApi'], 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
const requestQueryParams: PeopleContentQueryRequestModel = { skipCount: 10, maxItems: 20, sorting: { orderBy: 'firstName', direction: 'asc' } };
const expectedValue = { skipCount: 10, maxItems: 20, orderBy: ['firstName ASC'] };
@@ -105,7 +105,7 @@ describe('PeopleContentService', () => {
});
it('should not call listPeople api with sorting params if sorting is not defined', async () => {
const listPeopleSpy = spyOn(service.peopleApi, 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
const listPeopleSpy = spyOn(service['peopleApi'], 'listPeople').and.returnValue(Promise.resolve(fakeEcmUserList));
const requestQueryParams: PeopleContentQueryRequestModel = { skipCount: 10, maxItems: 20, sorting: undefined };
const expectedValue = { skipCount: 10, maxItems: 20 };
@@ -115,7 +115,7 @@ describe('PeopleContentService', () => {
});
it('should be able to create new person', (done) => {
spyOn(service.peopleApi, 'createPerson').and.returnValue(Promise.resolve(new PersonEntry({ entry: fakeEcmUser })));
spyOn(service['peopleApi'], 'createPerson').and.returnValue(Promise.resolve(new PersonEntry({ entry: fakeEcmUser })));
service.createPerson(createNewPersonMock).subscribe((person) => {
expect(person.id).toEqual('fake-id');
expect(person.email).toEqual('fakeEcm@ecmUser.com');
@@ -124,7 +124,7 @@ describe('PeopleContentService', () => {
});
it('should be able to call createPerson api with new person details', (done) => {
const createPersonSpy = spyOn(service.peopleApi, 'createPerson').and.returnValue(Promise.resolve(new PersonEntry({ entry: fakeEcmUser })));
const createPersonSpy = spyOn(service['peopleApi'], 'createPerson').and.returnValue(Promise.resolve(new PersonEntry({ entry: fakeEcmUser })));
service.createPerson(createNewPersonMock).subscribe((person) => {
expect(person.id).toEqual('fake-id');
expect(person.email).toEqual('fakeEcm@ecmUser.com');
@@ -134,7 +134,7 @@ describe('PeopleContentService', () => {
});
it('should be able to throw an error if createPerson api failed', (done) => {
const createPersonSpy = spyOn(service.peopleApi, 'createPerson').and.returnValue(Promise.reject({ message: 'failed to create new person' }));
const createPersonSpy = spyOn(service['peopleApi'], 'createPerson').and.returnValue(Promise.reject({ message: 'failed to create new person' }));
const logErrorSpy = spyOn(logService, 'error');
service.createPerson(createNewPersonMock).subscribe(
() => {},
@@ -147,7 +147,7 @@ describe('PeopleContentService', () => {
});
it('Should make the api call to check if the user is a content admin only once', async () => {
const getCurrentPersonSpy = spyOn(service.peopleApi, 'getPerson').and.returnValue(Promise.resolve(getFakeUserWithContentAdminCapability()));
const getCurrentPersonSpy = spyOn(service['peopleApi'], 'getPerson').and.returnValue(Promise.resolve(getFakeUserWithContentAdminCapability()));
expect(await service.isContentAdmin()).toBe(true);
expect(getCurrentPersonSpy.calls.count()).toEqual(1);

View File

@@ -50,12 +50,10 @@ export class PeopleContentService {
private hasContentAdminRole: boolean = false;
hasCheckedIsContentAdmin: boolean = false;
private _peopleApi: PeopleApi;
private peopleApi: PeopleApi;
constructor(private apiService: AlfrescoApiService, private logService: LogService) {}
get peopleApi() {
return this._peopleApi || (this._peopleApi = new PeopleApi(this.apiService.getInstance()));
constructor(private apiService: AlfrescoApiService, private logService: LogService) {
this.peopleApi = new PeopleApi(this.apiService.getInstance());
}
/**

View File

@@ -21,14 +21,20 @@ import { UserProcessModel } from '../models/user-process.model';
import { AlfrescoApiService } from './alfresco-api.service';
import { LogService } from './log.service';
import { catchError, map } from 'rxjs/operators';
import { TaskActionsApi, UsersApi, ResultListDataRepresentationLightUserRepresentation } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
})
export class PeopleProcessService {
constructor(private alfrescoJsApi: AlfrescoApiService,
private taskActionsApi: TaskActionsApi;
private userApi: UsersApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.taskActionsApi = new TaskActionsApi(this.apiService.getInstance());
this.userApi = new UsersApi(this.apiService.getInstance());
}
/**
@@ -62,7 +68,7 @@ export class PeopleProcessService {
* @returns Empty response when the update completes
*/
involveUserWithTask(taskId: string, idToInvolve: string): Observable<UserProcessModel[]> {
const node = {userId: idToInvolve};
const node = { userId: idToInvolve };
return from(this.involveUserToTaskApi(taskId, node))
.pipe(
catchError((err) => this.handleError(err))
@@ -76,27 +82,27 @@ export class PeopleProcessService {
* @returns Empty response when the update completes
*/
removeInvolvedUser(taskId: string, idToRemove: string): Observable<UserProcessModel[]> {
const node = {userId: idToRemove};
const node = { userId: idToRemove };
return from(this.removeInvolvedUserFromTaskApi(taskId, node))
.pipe(
catchError((err) => this.handleError(err))
);
}
private getWorkflowUserApi(options: any) {
return this.alfrescoJsApi.getInstance().activiti.usersWorkflowApi.getUsers(options);
private getWorkflowUserApi(options: any): Promise<ResultListDataRepresentationLightUserRepresentation> {
return this.userApi.getUsers(options);
}
private involveUserToTaskApi(taskId: string, node: any) {
return this.alfrescoJsApi.getInstance().activiti.taskActionsApi.involveUser(taskId, node);
return this.taskActionsApi.involveUser(taskId, node);
}
private removeInvolvedUserFromTaskApi(taskId: string, node: any) {
return this.alfrescoJsApi.getInstance().activiti.taskActionsApi.removeInvolvedUser(taskId, node);
return this.taskActionsApi.removeInvolvedUser(taskId, node);
}
private getUserProfileImageApi(userId: string): string {
return this.alfrescoJsApi.getInstance().activiti.userApi.getUserProfilePictureUrl(userId);
return this.userApi.getUserProfilePictureUrl(userId);
}
/**

View File

@@ -16,7 +16,7 @@
*/
import { Injectable } from '@angular/core';
import { RenditionEntry, RenditionPaging } from '@alfresco/js-api';
import { RenditionEntry, RenditionPaging, RenditionsApi, ContentApi } from '@alfresco/js-api';
import { Observable, from, interval, empty } from 'rxjs';
import { AlfrescoApiService } from './alfresco-api.service';
import { concatMap, switchMap, takeWhile, map } from 'rxjs/operators';
@@ -26,7 +26,12 @@ import { concatMap, switchMap, takeWhile, map } from 'rxjs/operators';
})
export class RenditionsService {
private renditionsApi: RenditionsApi;
private contentApi: ContentApi;
constructor(private apiService: AlfrescoApiService) {
this.renditionsApi = new RenditionsApi(this.apiService.getInstance());
this.contentApi = new ContentApi(this.apiService.getInstance());
}
/**
@@ -35,7 +40,7 @@ export class RenditionsService {
* @returns Information object for the rendition
*/
getAvailableRenditionForNode(nodeId: string): Observable<RenditionEntry> {
return from(this.apiService.renditionsApi.getRenditions(nodeId)).pipe(
return from(this.renditionsApi.listRenditions(nodeId)).pipe(
map((availableRenditions: RenditionPaging) => {
const renditionsAvailable: RenditionEntry[] = availableRenditions.list.entries.filter(
(rendition) => (rendition.entry.id === 'pdf' || rendition.entry.id === 'imgpreview'));
@@ -53,7 +58,7 @@ export class RenditionsService {
return this.getAvailableRenditionForNode(nodeId).pipe(
map((rendition: RenditionEntry) => {
if (rendition.entry.status !== 'CREATED') {
return from(this.apiService.renditionsApi.createRendition(nodeId, { id: rendition.entry.id }));
return from(this.renditionsApi.createRendition(nodeId, { id: rendition.entry.id }));
} else {
return empty();
}
@@ -114,7 +119,7 @@ export class RenditionsService {
* @returns URL string
*/
getRenditionUrl(nodeId: string, encoding: string): string {
return this.apiService.contentApi.getRenditionUrl(nodeId, encoding);
return this.contentApi.getRenditionUrl(nodeId, encoding);
}
/**
@@ -124,7 +129,7 @@ export class RenditionsService {
* @returns Information object about the rendition
*/
getRendition(nodeId: string, encoding: string): Observable<RenditionEntry> {
return from(this.apiService.renditionsApi.getRendition(nodeId, encoding));
return from(this.renditionsApi.getRendition(nodeId, encoding));
}
/**
@@ -133,7 +138,7 @@ export class RenditionsService {
* @returns Paged list of rendition details
*/
getRenditionsListByNodeId(nodeId: string): Observable<RenditionPaging> {
return from(this.apiService.renditionsApi.getRenditions(nodeId));
return from(this.renditionsApi.listRenditions(nodeId));
}
/**
@@ -143,7 +148,7 @@ export class RenditionsService {
* @returns Null response to indicate completion
*/
createRendition(nodeId: string, encoding: string): Observable<{}> {
return from(this.apiService.renditionsApi.createRendition(nodeId, { id: encoding }));
return from(this.renditionsApi.createRendition(nodeId, { id: encoding }));
}
/**

View File

@@ -16,17 +16,15 @@
*/
import { TestBed } from '@angular/core/testing';
import { searchMockApi, mockError, fakeSearch } from '../mock/search.service.mock';
import { mockError, fakeSearch } from '../mock/search.service.mock';
import { SearchService } from './search.service';
import { setupTestBed } from '../testing/setup-test-bed';
import { AlfrescoApiService } from './alfresco-api.service';
import { CoreTestingModule } from '../testing/core.testing.module';
import { TranslateModule } from '@ngx-translate/core';
describe('SearchService', () => {
let service: SearchService;
let apiService: AlfrescoApiService;
setupTestBed({
imports: [
@@ -37,16 +35,14 @@ describe('SearchService', () => {
beforeEach(() => {
service = TestBed.inject(SearchService);
apiService = TestBed.inject(AlfrescoApiService);
spyOn(apiService, 'getInstance').and.returnValue(searchMockApi);
});
it('should call search API with no additional options', (done) => {
const searchTerm = 'searchTerm63688';
spyOn(searchMockApi.core.queriesApi, 'findNodes').and.returnValue(Promise.resolve(fakeSearch));
spyOn(service.queriesApi, 'findNodes').and.returnValue(Promise.resolve(fakeSearch));
service.getNodeQueryResults(searchTerm).subscribe(
() => {
expect(searchMockApi.core.queriesApi.findNodes).toHaveBeenCalledWith(searchTerm, undefined);
expect(service.queriesApi.findNodes).toHaveBeenCalledWith(searchTerm, undefined);
done();
}
);
@@ -58,16 +54,17 @@ describe('SearchService', () => {
rootNodeId: '-root-',
nodeType: 'cm:content'
};
spyOn(searchMockApi.core.queriesApi, 'findNodes').and.returnValue(Promise.resolve(fakeSearch));
spyOn(service.queriesApi, 'findNodes').and.returnValue(Promise.resolve(fakeSearch));
service.getNodeQueryResults(searchTerm, options).subscribe(
() => {
expect(searchMockApi.core.queriesApi.findNodes).toHaveBeenCalledWith(searchTerm, options);
expect(service.queriesApi.findNodes).toHaveBeenCalledWith(searchTerm, options);
done();
}
);
});
it('should return search results returned from the API', (done) => {
spyOn(service.queriesApi, 'findNodes').and.returnValue(Promise.resolve(fakeSearch));
service.getNodeQueryResults('').subscribe(
(res: any) => {
expect(res).toBeDefined();
@@ -78,7 +75,7 @@ describe('SearchService', () => {
});
it('should notify errors returned from the API', (done) => {
spyOn(searchMockApi.core.queriesApi, 'findNodes').and.returnValue(Promise.reject(mockError));
spyOn(service.queriesApi, 'findNodes').and.returnValue(Promise.reject(mockError));
service.getNodeQueryResults('').subscribe(
() => {},
(res: any) => {

View File

@@ -16,7 +16,7 @@
*/
import { Injectable } from '@angular/core';
import { NodePaging, QueryBody, ResultSetPaging } from '@alfresco/js-api';
import { NodePaging, QueriesApi, QueryBody, ResultSetPaging, SearchApi } from '@alfresco/js-api';
import { Observable, Subject, from, throwError } from 'rxjs';
import { AlfrescoApiService } from './alfresco-api.service';
import { SearchConfigurationService } from './search-configuration.service';
@@ -27,9 +27,14 @@ import { SearchConfigurationService } from './search-configuration.service';
export class SearchService {
dataLoaded: Subject<ResultSetPaging> = new Subject();
queriesApi: QueriesApi;
searchApi: SearchApi;
constructor(private apiService: AlfrescoApiService,
private searchConfigurationService: SearchConfigurationService) {}
private searchConfigurationService: SearchConfigurationService) {
this.queriesApi = new QueriesApi(this.apiService.getInstance());
this.searchApi = new SearchApi(this.apiService.getInstance());
}
/**
* Gets a list of nodes that match the given search criteria.
@@ -38,7 +43,7 @@ export class SearchService {
* @returns List of nodes resulting from the search
*/
getNodeQueryResults(term: string, options?: SearchOptions): Observable<NodePaging> {
const promise = this.apiService.getInstance().core.queriesApi.findNodes(term, options);
const promise = this.queriesApi.findNodes(term, options);
promise.then((nodePaging: NodePaging) => {
this.dataLoaded.next(nodePaging);
@@ -56,7 +61,7 @@ export class SearchService {
*/
search(searchTerm: string, maxResults: number, skipCount: number): Observable<ResultSetPaging> {
const searchQuery = Object.assign(this.searchConfigurationService.generateQueryBody(searchTerm, maxResults, skipCount));
const promise = this.apiService.getInstance().search.searchApi.search(searchQuery);
const promise = this.searchApi.search(searchQuery);
promise.then((nodePaging: NodePaging) => {
this.dataLoaded.next(nodePaging);
@@ -71,7 +76,7 @@ export class SearchService {
* @returns List of search results
*/
searchByQueryBody(queryBody: QueryBody): Observable<ResultSetPaging> {
const promise = this.apiService.getInstance().search.searchApi.search(queryBody);
const promise = this.searchApi.search(queryBody);
promise.then((nodePaging: NodePaging) => {
this.dataLoaded.next(nodePaging);

View File

@@ -16,7 +16,7 @@
*/
import { Injectable } from '@angular/core';
import { NodePaging, SharedLinkEntry } from '@alfresco/js-api';
import { NodePaging, SharedLinkEntry, SharedlinksApi } from '@alfresco/js-api';
import { Observable, from, of, Subject } from 'rxjs';
import { AlfrescoApiService } from './alfresco-api.service';
import { UserPreferencesService } from './user-preferences.service';
@@ -28,13 +28,11 @@ import { catchError } from 'rxjs/operators';
export class SharedLinksApiService {
error = new Subject<{ statusCode: number, message: string }>();
private sharedLinksApi: SharedlinksApi;
constructor(private apiService: AlfrescoApiService,
private preferences: UserPreferencesService) {
}
private get sharedLinksApi() {
return this.apiService.getInstance().core.sharedlinksApi;
this.sharedLinksApi = new SharedlinksApi(this.apiService.getInstance());
}
/**
@@ -49,7 +47,7 @@ export class SharedLinksApiService {
include: ['properties', 'allowableOperations']
};
const queryOptions = Object.assign({}, defaultOptions, options);
const promise = this.sharedLinksApi.findSharedLinks(queryOptions);
const promise = this.sharedLinksApi.listSharedLinks(queryOptions);
return from(promise).pipe(
catchError((err) => of(err))
@@ -63,7 +61,7 @@ export class SharedLinksApiService {
* @returns The shared link just created
*/
createSharedLinks(nodeId: string, options: any = {}): Observable<SharedLinkEntry> {
const promise = this.sharedLinksApi.addSharedLink({ nodeId: nodeId }, options);
const promise = this.sharedLinksApi.createSharedLink({ nodeId: nodeId }, options);
return from(promise).pipe(
catchError((err) => of(err))

View File

@@ -40,10 +40,10 @@ import { LogService } from './log.service';
})
export class SitesService {
sitesApi: SitesApi;
private sitesApi: SitesApi;
constructor(private apiService: AlfrescoApiService, private logService: LogService) {
this.sitesApi = new SitesApi(apiService.getInstance());
this.sitesApi = new SitesApi(this.apiService.getInstance());
}
/**

View File

@@ -19,13 +19,11 @@ import { TestBed } from '@angular/core/testing';
import { ThumbnailService } from './thumbnail.service';
import { setupTestBed } from '../testing/setup-test-bed';
import { CoreTestingModule } from '../testing/core.testing.module';
import { AlfrescoApiService } from './alfresco-api.service';
import { TranslateModule } from '@ngx-translate/core';
describe('ThumbnailService', () => {
let service: ThumbnailService;
let apiService: AlfrescoApiService;
setupTestBed({
imports: [
@@ -36,7 +34,6 @@ describe('ThumbnailService', () => {
beforeEach(() => {
service = TestBed.inject(ThumbnailService);
apiService = TestBed.inject(AlfrescoApiService);
});
it('should return the correct icon for a plain text file', () => {
@@ -56,7 +53,7 @@ describe('ThumbnailService', () => {
});
it('should return the thumbnail URL for a content item', () => {
spyOn(apiService.contentApi, 'getDocumentThumbnailUrl').and.returnValue('/fake-thumbnail.png');
spyOn(service['contentApi'], 'getDocumentThumbnailUrl').and.returnValue('/fake-thumbnail.png');
expect(service.getDocumentThumbnailUrl('some-id')).toContain('/fake-thumbnail.png');
});
});

View File

@@ -20,7 +20,7 @@ import { Injectable } from '@angular/core';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import { AlfrescoApiService } from './alfresco-api.service';
import { NodeEntry } from '@alfresco/js-api';
import { ContentApi, NodeEntry } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
@@ -116,7 +116,7 @@ export class ThumbnailService {
'video/x-ms-asf': './assets/images/ft_ic_video.svg',
'video/x-ms-wmv': './assets/images/ft_ic_video.svg',
'video/x-msvideo': './assets/images/ft_ic_video.svg',
'video/x-rad-screenplay': './assets/images/ft_ic_video.svg',
'video/x-rad-screenplay': './assets/images/ft_ic_video.svg',
'video/x-sgi-movie': './assets/images/ft_ic_video.svg',
'video/x-matroska': './assets/images/ft_ic_video.svg',
'audio/mpeg': './assets/images/ft_ic_audio.svg',
@@ -164,7 +164,10 @@ export class ThumbnailService {
'task': './assets/images/task.svg'
};
private contentApi: ContentApi;
constructor(protected apiService: AlfrescoApiService, matIconRegistry: MatIconRegistry, sanitizer: DomSanitizer) {
this.contentApi = new ContentApi(apiService.getInstance());
Object.keys(this.mimeTypeIcons).forEach((key) => {
const url = sanitizer.bypassSecurityTrustResourceUrl(this.mimeTypeIcons[key]);
@@ -192,7 +195,7 @@ export class ThumbnailService {
nodeId = node.entry.id;
}
resultUrl = this.apiService.contentApi.getDocumentThumbnailUrl(nodeId, attachment, ticket);
resultUrl = this.contentApi.getDocumentThumbnailUrl(nodeId, attachment, ticket);
}
return resultUrl || this.DEFAULT_ICON;

View File

@@ -21,7 +21,6 @@ import { FileModel, FileUploadOptions, FileUploadStatus } from '../models/file.m
import { AppConfigModule } from '../app-config/app-config.module';
import { UploadService } from './upload.service';
import { AppConfigService } from '../app-config/app-config.service';
import { AlfrescoApiService } from './alfresco-api.service';
import { setupTestBed } from '../testing/setup-test-bed';
import { CoreTestingModule } from '../testing/core.testing.module';
@@ -35,7 +34,6 @@ declare let jasmine: any;
describe('UploadService', () => {
let service: UploadService;
let alfrescoApiService: AlfrescoApiService;
const mockProductInfo = new BehaviorSubject<EcmProductVersionModel>(null);
setupTestBed({
@@ -75,7 +73,6 @@ describe('UploadService', () => {
};
service = TestBed.inject(UploadService);
alfrescoApiService = TestBed.inject(AlfrescoApiService);
service.queue = [];
service.activeTask = null;
jasmine.Ajax.install();
@@ -309,7 +306,7 @@ describe('UploadService', () => {
});
it('If newVersion is set, name should be a param', () => {
const uploadFileSpy = spyOn(alfrescoApiService.getInstance().upload, 'uploadFile').and.callThrough();
const uploadFileSpy = spyOn(service['uploadApi'], 'uploadFile').and.callThrough();
const emitter = new EventEmitter();
@@ -359,7 +356,7 @@ describe('UploadService', () => {
});
it('should append to the request the extra upload options', () => {
const uploadFileSpy = spyOn(alfrescoApiService.getInstance().upload, 'uploadFile').and.callThrough();
const uploadFileSpy = spyOn(service['uploadApi'], 'uploadFile').and.callThrough();
const emitter = new EventEmitter();
const filesFake = new FileModel(
@@ -477,7 +474,7 @@ describe('UploadService', () => {
it('Should not pass rendition if it is disabled', () => {
mockProductInfo.next({ status: { isThumbnailGenerationEnabled: false } } as EcmProductVersionModel);
const uploadFileSpy = spyOn(alfrescoApiService.getInstance().upload, 'uploadFile').and.callThrough();
const uploadFileSpy = spyOn(service['uploadApi'], 'uploadFile').and.callThrough();
const emitter = new EventEmitter();
const filesFake = new FileModel(<File> { name: 'fake-name', size: 10 }, {

View File

@@ -29,6 +29,7 @@ import { FileModel, FileUploadProgress, FileUploadStatus } from '../models/file.
import { AlfrescoApiService } from './alfresco-api.service';
import { DiscoveryApiService } from './discovery-api.service';
import { filter } from 'rxjs/operators';
import { NodesApi, UploadApi, VersionsApi } from '@alfresco/js-api';
const MIN_CANCELLABLE_FILE_SIZE = 1000000;
const MAX_CANCELLABLE_FILE_PERCENTAGE = 50;
@@ -53,29 +54,19 @@ export class UploadService {
queueChanged: Subject<FileModel[]> = new Subject<FileModel[]>();
fileUpload: Subject<FileUploadEvent> = new Subject<FileUploadEvent>();
fileUploadStarting: Subject<FileUploadEvent> = new Subject<
FileUploadEvent
>();
fileUploadCancelled: Subject<FileUploadEvent> = new Subject<
FileUploadEvent
>();
fileUploadProgress: Subject<FileUploadEvent> = new Subject<
FileUploadEvent
>();
fileUploadAborted: Subject<FileUploadEvent> = new Subject<
FileUploadEvent
>();
fileUploadError: Subject<FileUploadErrorEvent> = new Subject<
FileUploadErrorEvent
>();
fileUploadComplete: Subject<FileUploadCompleteEvent> = new Subject<
FileUploadCompleteEvent
>();
fileUploadDeleted: Subject<FileUploadDeleteEvent> = new Subject<
FileUploadDeleteEvent
>();
fileUploadStarting: Subject<FileUploadEvent> = new Subject<FileUploadEvent>();
fileUploadCancelled: Subject<FileUploadEvent> = new Subject<FileUploadEvent>();
fileUploadProgress: Subject<FileUploadEvent> = new Subject<FileUploadEvent>();
fileUploadAborted: Subject<FileUploadEvent> = new Subject<FileUploadEvent>();
fileUploadError: Subject<FileUploadErrorEvent> = new Subject<FileUploadErrorEvent>();
fileUploadComplete: Subject<FileUploadCompleteEvent> = new Subject<FileUploadCompleteEvent>();
fileUploadDeleted: Subject<FileUploadDeleteEvent> = new Subject<FileUploadDeleteEvent>();
fileDeleted: Subject<string> = new Subject<string>();
private uploadApi: UploadApi;
private nodesApi: NodesApi;
private versionsApi: VersionsApi;
constructor(
protected apiService: AlfrescoApiService,
private appConfigService: AppConfigService,
@@ -85,6 +76,10 @@ export class UploadService {
.subscribe(({ status }) => {
this.isThumbnailGenerationEnabled = status.isThumbnailGenerationEnabled;
});
this.uploadApi = new UploadApi(apiService.getInstance());
this.nodesApi = new NodesApi(apiService.getInstance());
this.versionsApi = new VersionsApi(apiService.getInstance());
}
/**
@@ -255,19 +250,15 @@ export class UploadService {
}
if (file.id) {
return this.apiService
.getInstance()
.node.updateNodeContent(file.id, file.file, opts);
return this.nodesApi.updateNodeContent(file.id, <any> file.file, opts);
} else {
return this.apiService
.getInstance()
.upload.uploadFile(
file.file,
file.options.path,
file.options.parentId,
file.options,
opts
);
return this.uploadApi.uploadFile(
file.file,
file.options.path,
file.options.parentId,
file.options,
opts
);
}
}
@@ -307,7 +298,8 @@ export class UploadService {
}
}
})
.catch(() => {});
.catch(() => {
});
return promise;
}
@@ -420,16 +412,12 @@ export class UploadService {
}
private deleteAbortedNode(nodeId: string) {
this.apiService
.getInstance()
.core.nodesApi.deleteNode(nodeId, { permanent: true })
this.nodesApi.deleteNode(nodeId, { permanent: true })
.then(() => (this.abortedFile = undefined));
}
private deleteAbortedNodeVersion(nodeId: string, versionId: string) {
this.apiService
.getInstance()
.core.versionsApi.deleteVersion(nodeId, versionId)
this.versionsApi.deleteVersion(nodeId, versionId)
.then(() => (this.abortedFile = undefined));
}

View File

@@ -44,6 +44,5 @@ export const setupTestBed = (moduleDef: TestModuleMetadata) => {
.catch(done.fail);
}
);
afterAll(() => allowAngularToReset());
};

View File

@@ -1,104 +0,0 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { SimpleChange, SimpleChanges } from '@angular/core';
import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
import { MediaPlayerComponent } from './media-player.component';
import { setupTestBed } from '../../testing/setup-test-bed';
import { CoreTestingModule } from '../../testing/core.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { AlfrescoApiService } from '../../services';
import { NodeEntry, RenditionPaging } from '@alfresco/js-api';
describe('Test Media player component ', () => {
let component: MediaPlayerComponent;
let fixture: ComponentFixture<MediaPlayerComponent>;
let alfrescoApiService: AlfrescoApiService;
let change: SimpleChanges;
setupTestBed({
imports: [
TranslateModule.forRoot(),
CoreTestingModule
]
});
describe('Media tracks', () => {
beforeEach(() => {
fixture = TestBed.createComponent(MediaPlayerComponent);
alfrescoApiService = TestBed.inject(AlfrescoApiService);
change = { nodeId: new SimpleChange(null, 'nodeId', true) };
component = fixture.componentInstance;
component.urlFile = 'http://fake.url';
fixture.detectChanges();
});
it('should generate tracks for media file when webvtt rendition exists', fakeAsync(() => {
const fakeRenditionUrl = 'http://fake.rendition.url';
spyOn(alfrescoApiService.nodesApi, 'getNode').and.returnValue(
Promise.resolve(new NodeEntry({ entry: { name: 'file1', content: {} } }))
);
spyOn(alfrescoApiService.renditionsApi, 'getRenditions').and.returnValue(
Promise.resolve(new RenditionPaging({ list: { entries: [{ entry: { id: 'webvtt', status: 'CREATED' } }] } }))
);
spyOn(alfrescoApiService.contentApi, 'getContentUrl').and.returnValue('http://iam-fake.url');
spyOn(alfrescoApiService.contentApi, 'getRenditionUrl').and.returnValue(fakeRenditionUrl);
component.ngOnChanges(change);
tick();
fixture.detectChanges();
expect(component.tracks).toEqual([{ src: fakeRenditionUrl, kind: 'subtitles', label: 'ADF_VIEWER.SUBTITLES' }]);
}));
it('should not generate tracks for media file when webvtt rendition is not created', fakeAsync(() => {
spyOn(alfrescoApiService.nodesApi, 'getNode').and.returnValue(
Promise.resolve(new NodeEntry({ entry: { name: 'file1', content: {} } }))
);
spyOn(alfrescoApiService.renditionsApi, 'getRenditions').and.returnValue(
Promise.resolve(new RenditionPaging({ list: { entries: [{ entry: { id: 'webvtt', status: 'NOT_CREATED' } }] } }))
);
spyOn(alfrescoApiService.contentApi, 'getContentUrl').and.returnValue('http://iam-fake.url');
component.ngOnChanges(change);
tick();
fixture.detectChanges();
expect(component.tracks.length).toBe(0);
}));
it('should not generate tracks for media file when webvtt rendition does not exist', fakeAsync(() => {
spyOn(alfrescoApiService.nodesApi, 'getNode').and.returnValue(
Promise.resolve(new NodeEntry({ entry: { name: 'file1', content: {} } }))
);
spyOn(alfrescoApiService.renditionsApi, 'getRenditions').and.returnValue(
Promise.resolve(new RenditionPaging({ list: { entries: [] } }))
);
spyOn(alfrescoApiService.contentApi, 'getContentUrl').and.returnValue('http://iam-fake.url');
component.ngOnChanges(change);
tick();
fixture.detectChanges();
expect(component.tracks.length).toBe(0);
}));
});
});

View File

@@ -129,7 +129,6 @@ class ViewerWithCustomOpenWithComponent {
})
class ViewerWithCustomMoreActionsComponent {
}
describe('ViewerComponent', () => {
let component: ViewerComponent;
@@ -291,20 +290,17 @@ describe('ViewerComponent', () => {
it('should node without content show unkonwn', (done) => {
const displayName = 'the-name';
const nodeDetails = { name: displayName, id: '12' };
const contentUrl = '/content/url/path';
const alfrescoApiInstanceMock: any = {
nodes: {
getNodeInfo: () => Promise.resolve(nodeDetails),
getNode: () => Promise.resolve({ id: 'fake-node', entry: { content: {} } })
},
content: { getContentUrl: () => contentUrl }
};
component.nodeId = '12';
component.urlFile = null;
component.displayName = null;
spyOn(alfrescoApiService, 'getInstance').and.returnValue(alfrescoApiInstanceMock);
spyOn(component['nodesApi'], 'getNode').and.returnValue(Promise.resolve({
id: 'fake-node',
entry: { content: { name: displayName, id: '12' } }
}));
spyOn(component['contentApi'], 'getContentUrl').and.returnValue(contentUrl);
component.ngOnChanges();
fixture.whenStable().then(() => {
@@ -365,10 +361,10 @@ describe('ViewerComponent', () => {
done();
});
}, 25000);
});
});
it('should change display name every time node changes', fakeAsync(() => {
spyOn(alfrescoApiService.nodesApi, 'getNode').and.returnValues(
spyOn(component['nodesApi'], 'getNode').and.returnValues(
Promise.resolve(new NodeEntry({ entry: { name: 'file1', content: {} } })),
Promise.resolve(new NodeEntry({ entry: { name: 'file2', content: {} } }))
);
@@ -392,10 +388,16 @@ describe('ViewerComponent', () => {
}));
it('should append version of the file to the file content URL', fakeAsync(() => {
spyOn(alfrescoApiService.nodesApi, 'getNode').and.returnValue(
Promise.resolve(new NodeEntry({ entry: { name: 'file1', content: {}, properties: { 'cm:versionLabel' : '10'} } }))
spyOn(component['nodesApi'], 'getNode').and.returnValue(
Promise.resolve(new NodeEntry({
entry: {
name: 'file1',
content: {},
properties: { 'cm:versionLabel': '10' }
}
}))
);
spyOn(alfrescoApiService.versionsApi, 'getVersion').and.returnValue(Promise.resolve(undefined));
spyOn(component['versionsApi'], 'getVersion').and.returnValue(Promise.resolve(undefined));
component.nodeId = 'id1';
component.urlFile = null;
@@ -412,11 +414,11 @@ describe('ViewerComponent', () => {
}));
it('should change display name every time node\`s version changes', fakeAsync(() => {
spyOn(alfrescoApiService.nodesApi, 'getNode').and.returnValue(
spyOn(component['nodesApi'], 'getNode').and.returnValue(
Promise.resolve(new NodeEntry({ entry: { name: 'node1', content: {} } }))
);
spyOn(alfrescoApiService.versionsApi, 'getVersion').and.returnValues(
spyOn(component['versionsApi'], 'getVersion').and.returnValues(
Promise.resolve(new VersionEntry({ entry: { name: 'file1', content: {} } })),
Promise.resolve(new VersionEntry({ entry: { name: 'file2', content: {} } }))
);
@@ -441,10 +443,10 @@ describe('ViewerComponent', () => {
}));
it('should update node only if node name changed', fakeAsync(() => {
spyOn(alfrescoApiService.nodesApi, 'getNode').and.returnValues(
spyOn(component['nodesApi'], 'getNode').and.returnValues(
Promise.resolve(new NodeEntry({ entry: { name: 'file1', content: {} } }))
);
spyOn(alfrescoApiService.contentApi, 'getContentUrl').and.returnValues('http://iam-fake.url');
spyOn(component['contentApi'], 'getContentUrl').and.returnValues('http://iam-fake.url');
spyOn(component, 'getViewerTypeByExtension').and.returnValue('pdf');
component.urlFile = null;
@@ -684,28 +686,25 @@ describe('ViewerComponent', () => {
component.nodeId = '12';
component.urlFile = '';
const displayName = 'the-name';
const node = new NodeEntry({ entry: { name: displayName, id: '12', content: { mimeType: 'txt' } } });
const nodeDetails = { name: displayName, id: '12', content: { mimeType: 'txt' } };
const contentUrl = '/content/url/path';
const alfrescoApiInstanceMock: any = {
nodes: {
getNodeInfo: () => Promise.resolve(nodeDetails),
getNode: () => Promise.resolve(node)
},
content: { getContentUrl: () => contentUrl }
const nodeDetails = {
id: 'fake-node',
entry: { name: displayName, id: '12', content: { mimeType: 'txt' } }
};
spyOn(alfrescoApiService, 'getInstance').and.returnValue(alfrescoApiInstanceMock);
const contentUrl = '/content/url/path';
spyOn(component['nodesApi'], 'getNode').and.returnValue(Promise.resolve(nodeDetails));
spyOn(component['contentApi'], 'getContentUrl').and.returnValue(contentUrl);
component.ngOnChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(component.nodeEntry).toBe(node);
expect(component.nodeEntry).toBe(nodeDetails);
done();
});
});
it('should render close viewer button if it is not a shared link', (done) => {
fixture.detectChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
@@ -716,7 +715,6 @@ describe('ViewerComponent', () => {
});
it('should emit `showViewerChange` event on close', async () => {
spyOn(component.showViewerChange, 'emit');
const button: HTMLButtonElement = element.querySelector('[data-automation-id="adf-toolbar-back"]') as HTMLButtonElement;
@@ -729,7 +727,7 @@ describe('ViewerComponent', () => {
});
it('should not render close viewer button if it is a shared link', (done) => {
spyOn(alfrescoApiService.getInstance().core.sharedlinksApi, 'getSharedLink')
spyOn(component['sharedLinksApi'], 'getSharedLink')
.and.returnValue(Promise.reject({}));
component.sharedLinkId = 'the-Shared-Link-id';
@@ -803,7 +801,7 @@ describe('ViewerComponent', () => {
const event = new KeyboardEvent('keydown', {
bubbles: true,
keyCode: 27
} as KeyboardEventInit );
} as KeyboardEventInit);
const dialogRef = dialog.open(DummyDialogComponent);
dialogRef.afterClosed().subscribe(() => {
@@ -886,7 +884,7 @@ describe('ViewerComponent', () => {
describe('error handling', () => {
it('should show unknown view when node file not found', (done) => {
spyOn(alfrescoApiService.getInstance().nodes, 'getNode')
spyOn(component['nodesApi'], 'getNode')
.and.returnValue(Promise.reject({}));
component.nodeId = 'the-node-id-of-the-file-to-preview';
@@ -902,7 +900,7 @@ describe('ViewerComponent', () => {
});
it('should show unknown view when sharedLink file not found', (done) => {
spyOn(alfrescoApiService.getInstance().core.sharedlinksApi, 'getSharedLink')
spyOn(component['sharedLinksApi'], 'getSharedLink')
.and.returnValue(Promise.reject({}));
component.sharedLinkId = 'the-Shared-Link-id';
@@ -919,7 +917,7 @@ describe('ViewerComponent', () => {
});
it('should raise an event when the shared link is invalid', (done) => {
spyOn(alfrescoApiService.getInstance().core.sharedlinksApi, 'getSharedLink')
spyOn(component['sharedLinksApi'], 'getSharedLink')
.and.returnValue(Promise.reject({}));
component.invalidSharedLink.subscribe(() => {
@@ -965,10 +963,17 @@ describe('ViewerComponent', () => {
});
it('should update version when emitted by image-viewer and user has update permissions', () => {
spyOn(uploadService, 'uploadFilesInTheQueue').and.callFake(() => {});
spyOn(uploadService, 'uploadFilesInTheQueue').and.callFake(() => {
});
spyOn(uploadService, 'addToQueue');
component.readOnly = false;
component.nodeEntry = new NodeEntry({ entry: { name: 'fakeImage.png', id: '12', content: { mimeType: 'img/png' } } });
component.nodeEntry = new NodeEntry({
entry: {
name: 'fakeImage.png',
id: '12',
content: { mimeType: 'img/png' }
}
});
const data = atob('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==');
const fakeBlob = new Blob([data], { type: 'image/png' });
const newImageFile: File = new File([fakeBlob], component?.nodeEntry?.entry?.name, { type: component?.nodeEntry?.entry?.content?.mimeType });
@@ -990,9 +995,16 @@ describe('ViewerComponent', () => {
});
it('should not update version when emitted by image-viewer and user doesn`t have update permissions', () => {
spyOn(uploadService, 'uploadFilesInTheQueue').and.callFake(() => {});
spyOn(uploadService, 'uploadFilesInTheQueue').and.callFake(() => {
});
component.readOnly = true;
component.nodeEntry = new NodeEntry({ entry: { name: 'fakeImage.png', id: '12', content: { mimeType: 'img/png' } } });
component.nodeEntry = new NodeEntry({
entry: {
name: 'fakeImage.png',
id: '12',
content: { mimeType: 'img/png' }
}
});
const data = atob('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==');
const fakeBlob = new Blob([data], { type: 'image/png' });
component.onSubmitFile(fakeBlob);
@@ -1062,31 +1074,26 @@ describe('ViewerComponent', () => {
describe('display name property override by nodeId', () => {
const displayName = 'the-name';
const nodeDetails = new NodeEntry({ entry: { name: displayName, id: '12', content: { mimeType: 'txt' } } });
const contentUrl = '/content/url/path';
const alfrescoApiInstanceMock: any = {
nodes: {
getNode: () => Promise.resolve(nodeDetails)
},
content: { getContentUrl: () => contentUrl }
};
const nodeDetails = new NodeEntry({ entry: { name: 'node-id-name', id: '12', content: { mimeType: 'txt' } } });
it('should use the node name if displayName is NOT set and nodeId is set', (done) => {
spyOn(component['nodesApi'], 'getNode').and.returnValue(Promise.resolve(nodeDetails));
spyOn(component['contentApi'], 'getContentUrl').and.returnValue(contentUrl);
component.nodeId = '12';
component.urlFile = null;
component.displayName = null;
spyOn(alfrescoApiService, 'getInstance').and.returnValue(alfrescoApiInstanceMock);
component.displayName = 'the-name';
component.ngOnChanges();
fixture.whenStable().then(() => {
fixture.detectChanges();
expect(element.querySelector('#adf-viewer-display-name').textContent).toEqual(displayName);
expect(element.querySelector('#adf-viewer-display-name').textContent).toEqual('the-name');
done();
});
});
});
});
});
describe('Viewer component - Full Screen Mode - Mocking fixture element', () => {

View File

@@ -20,7 +20,15 @@ import {
Input, OnChanges, Output, TemplateRef,
ViewEncapsulation, OnInit, OnDestroy
} from '@angular/core';
import { SharedLinkEntry, Node, Version, RenditionEntry, NodeEntry, VersionEntry } from '@alfresco/js-api';
import {
SharedLinkEntry,
Node,
Version,
RenditionEntry,
NodeEntry,
VersionEntry,
SharedlinksApi, VersionsApi, NodesApi, ContentApi
} from '@alfresco/js-api';
import { BaseEvent } from '../../events';
import { AlfrescoApiService } from '../../services/alfresco-api.service';
import { LogService } from '../../services/log.service';
@@ -249,6 +257,11 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
private shouldCloseViewer = true;
private keyDown$ = fromEvent<KeyboardEvent>(document, 'keydown');
private sharedLinksApi: SharedlinksApi;
private versionsApi: VersionsApi;
private nodesApi: NodesApi;
private contentApi: ContentApi;
constructor(private apiService: AlfrescoApiService,
private viewUtilService: ViewUtilService,
private logService: LogService,
@@ -257,6 +270,10 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
private uploadService: UploadService,
private el: ElementRef,
public dialog: MatDialog) {
this.sharedLinksApi = new SharedlinksApi(this.apiService.getInstance());
this.versionsApi = new VersionsApi(this.apiService.getInstance());
this.nodesApi = new NodesApi(this.apiService.getInstance());
this.contentApi = new ContentApi(this.apiService.getInstance());
viewUtilService.maxRetries = this.maxRetries;
}
@@ -329,44 +346,52 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
this.setUpUrlFile();
this.isLoading = false;
} else if (this.nodeId) {
this.apiService.nodesApi.getNode(this.nodeId, { include: ['allowableOperations'] }).then(
(node: NodeEntry) => {
this.nodeEntry = node;
if (this.versionId) {
this.apiService.versionsApi.getVersion(this.nodeId, this.versionId).then(
(version: VersionEntry) => {
this.versionEntry = version;
this.setUpNodeFile(node.entry, version.entry).then(() => {
this.isLoading = false;
});
}
);
} else {
this.setUpNodeFile(node.entry).then(() => {
this.setupNode();
} else if (this.sharedLinkId) {
this.setupSharedLink();
}
}
}
private setupSharedLink() {
this.allowGoBack = false;
this.sharedLinksApi.getSharedLink(this.sharedLinkId).then(
(sharedLinkEntry: SharedLinkEntry) => {
this.setUpSharedLinkFile(sharedLinkEntry);
this.isLoading = false;
},
() => {
this.isLoading = false;
this.logService.error('This sharedLink does not exist');
this.invalidSharedLink.next();
});
}
private setupNode() {
this.nodesApi.getNode(this.nodeId, { include: ['allowableOperations'] }).then(
(node: NodeEntry) => {
this.nodeEntry = node;
if (this.versionId) {
this.versionsApi.getVersion(this.nodeId, this.versionId).then(
(version: VersionEntry) => {
this.versionEntry = version;
this.setUpNodeFile(node.entry, version.entry).then(() => {
this.isLoading = false;
});
}
},
() => {
);
} else {
this.setUpNodeFile(node.entry).then(() => {
this.isLoading = false;
this.logService.error('This node does not exist');
}
);
} else if (this.sharedLinkId) {
this.allowGoBack = false;
this.apiService.sharedLinksApi.getSharedLink(this.sharedLinkId).then(
(sharedLinkEntry: SharedLinkEntry) => {
this.setUpSharedLinkFile(sharedLinkEntry);
this.isLoading = false;
},
() => {
this.isLoading = false;
this.logService.error('This sharedLink does not exist');
this.invalidSharedLink.next();
});
}
},
() => {
this.isLoading = false;
this.logService.error('This node does not exist');
}
}
);
}
private setUpBlobData() {
@@ -414,8 +439,8 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
const currentFileVersion = this.nodeEntry?.entry?.properties && this.nodeEntry.entry.properties['cm:versionLabel'] ?
encodeURI(this.nodeEntry?.entry?.properties['cm:versionLabel']) : encodeURI('1.0');
this.urlFileContent = versionData ? this.apiService.contentApi.getVersionContentUrl(this.nodeId, versionData.id) :
this.apiService.contentApi.getContentUrl(this.nodeId);
this.urlFileContent = versionData ? this.contentApi.getVersionContentUrl(this.nodeId, versionData.id) :
this.contentApi.getContentUrl(this.nodeId);
this.urlFileContent = this.cacheBusterNumber ? this.urlFileContent + '&' + currentFileVersion + '&' + this.cacheBusterNumber :
this.urlFileContent + '&' + currentFileVersion;
@@ -450,7 +475,7 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
this.extension = this.getFileExtension(details.entry.name);
this.fileName = details.entry.name;
this.urlFileContent = this.apiService.contentApi.getSharedLinkContentUrl(this.sharedLinkId, false);
this.urlFileContent = this.contentApi.getSharedLinkContentUrl(this.sharedLinkId, false);
this.viewerType = this.getViewerTypeByMimeType(this.mimeType);
if (this.viewerType === 'unknown') {
@@ -467,7 +492,7 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
toggleSidebar() {
this.showRightSidebar = !this.showRightSidebar;
if (this.showRightSidebar && this.nodeId) {
this.apiService.getInstance().nodes.getNode(this.nodeId, { include: ['allowableOperations'] })
this.nodesApi.getNode(this.nodeId, { include: ['allowableOperations'] })
.then((nodeEntry: NodeEntry) => {
this.sidebarRightTemplateContext.node = nodeEntry.entry;
});
@@ -477,7 +502,7 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
toggleLeftSidebar() {
this.showLeftSidebar = !this.showLeftSidebar;
if (this.showRightSidebar && this.nodeId) {
this.apiService.getInstance().nodes.getNode(this.nodeId, { include: ['allowableOperations'] })
this.nodesApi.getNode(this.nodeId, { include: ['allowableOperations'] })
.then((nodeEntry: NodeEntry) => {
this.sidebarLeftTemplateContext.node = nodeEntry.entry;
});
@@ -662,18 +687,18 @@ export class ViewerComponent implements OnChanges, OnInit, OnDestroy {
private async displaySharedLinkRendition(sharedId: string) {
try {
const rendition: RenditionEntry = await this.apiService.renditionsApi.getSharedLinkRendition(sharedId, 'pdf');
const rendition: RenditionEntry = await this.sharedLinksApi.getSharedLinkRendition(sharedId, 'pdf');
if (rendition.entry.status.toString() === 'CREATED') {
this.viewerType = 'pdf';
this.urlFileContent = this.apiService.contentApi.getSharedLinkRenditionUrl(sharedId, 'pdf');
this.urlFileContent = this.contentApi.getSharedLinkRenditionUrl(sharedId, 'pdf');
}
} catch (error) {
this.logService.error(error);
try {
const rendition: RenditionEntry = await this.apiService.renditionsApi.getSharedLinkRendition(sharedId, 'imgpreview');
const rendition: RenditionEntry = await this.sharedLinksApi.getSharedLinkRendition(sharedId, 'imgpreview');
if (rendition.entry.status.toString() === 'CREATED') {
this.viewerType = 'image';
this.urlFileContent = this.apiService.contentApi.getSharedLinkRenditionUrl(sharedId, 'imgpreview');
this.urlFileContent = this.contentApi.getSharedLinkRenditionUrl(sharedId, 'imgpreview');
}
} catch (error) {
this.logService.error(error);

View File

@@ -16,7 +16,7 @@
*/
import { Injectable } from '@angular/core';
import { RenditionEntry, RenditionPaging } from '@alfresco/js-api';
import { ContentApi, RenditionEntry, RenditionPaging, RenditionsApi, VersionsApi } from '@alfresco/js-api';
import { AlfrescoApiService } from '../../services/alfresco-api.service';
import { LogService } from '../../services/log.service';
import { Subject } from 'rxjs';
@@ -33,7 +33,7 @@ export class ViewUtilService {
* Content groups based on categorization of files that can be viewed in the web browser. This
* implementation or grouping is tied to the definition the ng component: ViewerComponent
*/
// tslint:disable-next-line:variable-name
// tslint:disable-next-line:variable-name
static ContentGroup = {
IMAGE: 'image',
MEDIA: 'media',
@@ -74,9 +74,16 @@ export class ViewUtilService {
viewerTypeChange: Subject<string> = new Subject<string>();
urlFileContentChange: Subject<string> = new Subject<string>();
renditionsApi: RenditionsApi;
contentApi: ContentApi;
versionsApi: VersionsApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService,
private translateService: TranslationService) {
this.renditionsApi = new RenditionsApi(this.apiService.getInstance());
this.contentApi = new ContentApi(this.apiService.getInstance());
this.versionsApi = new VersionsApi(this.apiService.getInstance());
}
/**
@@ -115,7 +122,7 @@ export class ViewUtilService {
this.getRendition(nodeId, ViewUtilService.ContentGroup.PDF)
.then((value) => {
const url: string = this.getRenditionUrl(nodeId, type, (value ? true : false));
const url: string = this.getRenditionUrl(nodeId, type, (!!value));
const printType = (type === ViewUtilService.ContentGroup.PDF
|| type === ViewUtilService.ContentGroup.TEXT)
? ViewUtilService.ContentGroup.PDF : type;
@@ -129,12 +136,12 @@ export class ViewUtilService {
getRenditionUrl(nodeId: string, type: string, renditionExists: boolean): string {
return (renditionExists && type !== ViewUtilService.ContentGroup.IMAGE) ?
this.apiService.contentApi.getRenditionUrl(nodeId, ViewUtilService.ContentGroup.PDF) :
this.apiService.contentApi.getContentUrl(nodeId, false);
this.contentApi.getRenditionUrl(nodeId, ViewUtilService.ContentGroup.PDF) :
this.contentApi.getContentUrl(nodeId, false);
}
private async waitRendition(nodeId: string, renditionId: string, retries: number): Promise<RenditionEntry> {
const rendition = await this.apiService.renditionsApi.getRendition(nodeId, renditionId);
const rendition = await this.renditionsApi.getRendition(nodeId, renditionId);
if (this.maxRetries < retries) {
const status = rendition.entry.status.toString();
@@ -170,7 +177,7 @@ export class ViewUtilService {
}
async getRendition(nodeId: string, renditionId: string): Promise<RenditionEntry> {
const renditionPaging: RenditionPaging = await this.apiService.renditionsApi.getRenditions(nodeId);
const renditionPaging: RenditionPaging = await this.renditionsApi.listRenditions(nodeId);
let rendition: RenditionEntry = renditionPaging.list.entries.find((renditionEntry: RenditionEntry) => renditionEntry.entry.id.toLowerCase() === renditionId);
if (rendition) {
@@ -178,7 +185,7 @@ export class ViewUtilService {
if (status === 'NOT_CREATED') {
try {
await this.apiService.renditionsApi.createRendition(nodeId, { id: renditionId });
await this.renditionsApi.createRendition(nodeId, { id: renditionId });
rendition = await this.waitRendition(nodeId, renditionId, 0);
} catch (err) {
this.logService.error(err);
@@ -201,8 +208,8 @@ export class ViewUtilService {
this.viewerTypeChange.next('image');
}
const urlFileContent = versionId ? this.apiService.contentApi.getVersionRenditionUrl(nodeId, versionId, renditionId) :
this.apiService.contentApi.getRenditionUrl(nodeId, renditionId);
const urlFileContent = versionId ? this.contentApi.getVersionRenditionUrl(nodeId, versionId, renditionId) :
this.contentApi.getRenditionUrl(nodeId, renditionId);
this.urlFileContentChange.next(urlFileContent);
}
} catch (err) {
@@ -213,8 +220,8 @@ export class ViewUtilService {
private async resolveNodeRendition(nodeId: string, renditionId: string, versionId?: string): Promise<RenditionEntry> {
renditionId = renditionId.toLowerCase();
const supportedRendition: RenditionPaging = versionId ? await this.apiService.versionsApi.listVersionRenditions(nodeId, versionId) :
await this.apiService.renditionsApi.getRenditions(nodeId);
const supportedRendition: RenditionPaging = versionId ? await this.versionsApi.listVersionRenditions(nodeId, versionId) :
await this.renditionsApi.listRenditions(nodeId);
let rendition: RenditionEntry = supportedRendition.list.entries.find((renditionEntry: RenditionEntry) => renditionEntry.entry.id.toLowerCase() === renditionId);
if (!rendition) {
@@ -228,11 +235,11 @@ export class ViewUtilService {
if (status === 'NOT_CREATED') {
try {
if (versionId) {
await this.apiService.versionsApi.createVersionRendition(nodeId, versionId, { id: renditionId }).then(() => {
await this.versionsApi.createVersionRendition(nodeId, versionId, { id: renditionId }).then(() => {
this.viewerTypeChange.next('in_creation');
});
} else {
await this.apiService.renditionsApi.createRendition(nodeId, { id: renditionId }).then(() => {
await this.renditionsApi.createRendition(nodeId, { id: renditionId }).then(() => {
this.viewerTypeChange.next('in_creation');
});
}
@@ -259,7 +266,7 @@ export class ViewUtilService {
currentRetry++;
if (this.maxRetries >= currentRetry) {
if (versionId) {
this.apiService.versionsApi.getVersionRendition(nodeId, versionId, renditionId).then((rendition: RenditionEntry) => {
this.versionsApi.getVersionRendition(nodeId, versionId, renditionId).then((rendition: RenditionEntry) => {
const status: string = rendition.entry.status.toString();
if (status === 'CREATED') {
@@ -271,7 +278,7 @@ export class ViewUtilService {
return reject();
});
} else {
this.apiService.renditionsApi.getRendition(nodeId, renditionId).then((rendition: RenditionEntry) => {
this.renditionsApi.getRendition(nodeId, renditionId).then((rendition: RenditionEntry) => {
const status: string = rendition.entry.status.toString();
if (status === 'CREATED') {
@@ -298,8 +305,8 @@ export class ViewUtilService {
this.viewerTypeChange.next('image');
}
const urlFileContent = versionId ? this.apiService.contentApi.getVersionRenditionUrl(nodeId, versionId, renditionId) :
this.apiService.contentApi.getRenditionUrl(nodeId, renditionId);
const urlFileContent = versionId ? this.contentApi.getVersionRenditionUrl(nodeId, versionId, renditionId) :
this.contentApi.getRenditionUrl(nodeId, renditionId);
this.urlFileContentChange.next(urlFileContent);
}
@@ -310,7 +317,7 @@ export class ViewUtilService {
if (value) {
tracks.push({
kind: 'subtitles',
src: this.apiService.contentApi.getRenditionUrl(nodeId, ViewUtilService.SUBTITLES_RENDITION_NAME),
src: this.contentApi.getRenditionUrl(nodeId, ViewUtilService.SUBTITLES_RENDITION_NAME),
label: this.translateService.instant('ADF_VIEWER.SUBTITLES')
});
}
@@ -324,7 +331,7 @@ export class ViewUtilService {
}
private async isRenditionAvailable(nodeId: string, renditionId: string): Promise<boolean> {
const renditionPaging: RenditionPaging = await this.apiService.renditionsApi.getRenditions(nodeId);
const renditionPaging: RenditionPaging = await this.renditionsApi.listRenditions(nodeId);
const rendition: RenditionEntry = renditionPaging.list.entries.find((renditionEntry: RenditionEntry) => renditionEntry.entry.id.toLowerCase() === renditionId);
return rendition?.entry?.status?.toString() === 'CREATED' || false;