[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
@@ -31,7 +31,8 @@ import {
import { ActivatedRoute, Router } from '@angular/router';
import {
Pagination,
UserProcessInstanceFilterRepresentation
UserProcessInstanceFilterRepresentation,
ScriptFilesApi
} from '@alfresco/js-api';
import {
FORM_FIELD_VALIDATORS, FormRenderingService, FormService,
@@ -167,6 +168,7 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
];
private onDestroy$ = new Subject<boolean>();
private scriptFileApi: ScriptFilesApi;
constructor(private elementRef: ElementRef,
private route: ActivatedRoute,
@@ -181,6 +183,7 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
private notificationService: NotificationService,
private preferenceService: UserPreferencesService) {
this.scriptFileApi = new ScriptFilesApi(this.apiService.getInstance());
this.defaultProcessName = this.appConfig.get<string>('adf-start-process.name');
this.defaultProcessDefinitionName = this.appConfig.get<string>('adf-start-process.processDefinitionName');
this.defaultTaskName = this.appConfig.get<string>('adf-start-task.name');
@@ -488,7 +491,7 @@ export class ProcessServiceComponent implements AfterViewInit, OnDestroy, OnInit
}
loadStencilScriptsInPageFromProcessService() {
this.apiService.getInstance().activiti.scriptFileApi.getControllers().then((response) => {
this.scriptFileApi.getControllers().then((response) => {
if (response) {
const stencilScript = document.createElement('script');
stencilScript.type = 'text/javascript';
@@ -1,199 +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 { AspectEntry, AspectPaging } from '@alfresco/js-api';
import { TestBed } from '@angular/core/testing';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { TranslateModule } from '@ngx-translate/core';
import { AlfrescoApiService, AppConfigService, LogService, setupTestBed } from 'core';
import { of, Subject, throwError } from 'rxjs';
import { ContentTestingModule } from '../testing/content.testing.module';
import { AspectListService } from './aspect-list.service';
const aspectListMock: AspectEntry[] = [{
entry: {
parentId: 'frs:aspectZero',
id: 'frs:AspectOne',
description: 'First Aspect with random description',
title: 'FirstAspect',
properties: [
{
id: 'channelPassword',
title: 'The authenticated channel password',
dataType: 'd:propA'
},
{
id: 'channelUsername',
title: 'The authenticated channel username',
dataType: 'd:propB'
}
]
}
},
{
entry: {
parentId: 'frs:AspectZer',
id: 'frs:SecondAspect',
description: 'Second Aspect description',
title: 'SecondAspect',
properties: [
{
id: 'assetId',
title: 'Published Asset Id',
dataType: 'd:text'
},
{
id: 'assetUrl',
title: 'Published Asset URL',
dataType: 'd:text'
}
]
}
}];
const customAspectListMock: AspectEntry[] = [{
entry: {
parentId: 'frs:aspectZero',
id: 'frs:AspectCustom',
description: 'First Aspect with random description',
title: 'FirstAspect',
properties: [
{
id: 'channelPassword',
title: 'The authenticated channel password',
dataType: 'd:propA'
},
{
id: 'channelUsername',
title: 'The authenticated channel username',
dataType: 'd:propB'
}
]
}
}];
const listAspectResp: AspectPaging = {
list : {
entries: aspectListMock
}
};
const customListAspectResp: AspectPaging = {
list : {
entries: customAspectListMock
}
};
describe('AspectListService', () => {
describe('should open the dialog', () => {
let service: AspectListService;
let materialDialog: MatDialog;
let spyOnDialogOpen: jasmine.Spy;
let spyOnDialogClose: jasmine.Spy;
const afterOpenObservable: Subject<any> = new Subject();
setupTestBed({
imports: [
TranslateModule.forRoot(),
ContentTestingModule,
MatDialogModule
]
});
beforeEach(() => {
service = TestBed.inject(AspectListService);
materialDialog = TestBed.inject(MatDialog);
spyOnDialogOpen = spyOn(materialDialog, 'open').and.returnValue({
afterOpen: () => afterOpenObservable,
afterClosed: () => of({}),
componentInstance: {
error: new Subject<any>()
}
} as any);
spyOnDialogClose = spyOn(materialDialog, 'closeAll');
});
it('should open the aspect list dialog', () => {
service.openAspectListDialog();
expect(spyOnDialogOpen).toHaveBeenCalled();
});
it('should close the dialog', () => {
service.close();
expect(spyOnDialogClose).toHaveBeenCalled();
});
});
describe('should fetch the list of the aspects', () => {
let service: AspectListService;
let appConfigService: AppConfigService;
let apiService: AlfrescoApiService;
let logService: LogService;
let aspectTypesApi: any;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ContentTestingModule]
});
aspectTypesApi = jasmine.createSpyObj('AspectsApi', ['listAspects']);
appConfigService = TestBed.inject(AppConfigService);
apiService = TestBed.inject(AlfrescoApiService);
logService = TestBed.inject(LogService);
spyOn(appConfigService, 'get').and.returnValue({ 'default': ['frs:AspectOne'] });
spyOnProperty(apiService, 'aspectsApi').and.returnValue(aspectTypesApi);
service = TestBed.inject(AspectListService);
});
it('should get the list of only available aspects', (done) => {
aspectTypesApi.listAspects.and.returnValues(of(listAspectResp), of(customListAspectResp));
service.getAspects().subscribe((list) => {
expect(list.length).toBe(2);
expect(list[0].entry.id).toBe('frs:AspectOne');
expect(list[1].entry.id).toBe('frs:AspectCustom');
done();
});
});
it('should return a value when the standard aspect call fails', (done) => {
spyOn(logService, 'error').and.stub();
aspectTypesApi.listAspects.and.returnValues(throwError('Insert Coin'), of(customListAspectResp));
service.getAspects().subscribe((list) => {
expect(list.length).toBe(1);
expect(list[0].entry.id).toBe('frs:AspectCustom');
expect(logService.error).toHaveBeenCalled();
done();
});
});
it('should return a value when the custom aspect call fails', (done) => {
spyOn(logService, 'error').and.stub();
aspectTypesApi.listAspects.and.returnValues(of(listAspectResp), throwError('Insert Coin'));
service.getAspects().subscribe((list) => {
expect(list.length).toBe(1);
expect(list[0].entry.id).toBe('frs:AspectOne');
expect(logService.error).toHaveBeenCalled();
done();
});
});
});
});
@@ -22,17 +22,20 @@ import { from, Observable, of, Subject, zip } from 'rxjs';
import { AspectListDialogComponentData } from './aspect-list-dialog-data.interface';
import { AspectListDialogComponent } from './aspect-list-dialog.component';
import { catchError, map } from 'rxjs/operators';
import { AspectEntry, AspectPaging } from '@alfresco/js-api';
import { AspectEntry, AspectPaging, AspectsApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
})
export class AspectListService {
private aspectsApi: AspectsApi;
constructor(private alfrescoApiService: AlfrescoApiService,
private appConfigService: AppConfigService,
private dialog: MatDialog,
private logService: LogService) {
this.aspectsApi = new AspectsApi(this.alfrescoApiService.getInstance());
}
getAspects(): Observable<AspectEntry[]> {
@@ -50,7 +53,7 @@ export class AspectListService {
where,
include: ['properties']
};
return from(this.alfrescoApiService.aspectsApi.listAspects(opts))
return from(this.aspectsApi.listAspects(opts))
.pipe(
map((result: AspectPaging) => this.filterAspectByConfig(whiteList, result?.list?.entries)),
catchError((error) => {
@@ -66,7 +69,7 @@ export class AspectListService {
where,
include: ['properties']
};
return from(this.alfrescoApiService.aspectsApi.listAspects(opts))
return from(this.aspectsApi.listAspects(opts))
.pipe(
map((result: AspectPaging) => result?.list?.entries),
catchError((error) => {
@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { AlfrescoApiService, AppConfigService, setupTestBed } from '@alfresco/adf-core';
import { AppConfigService, setupTestBed } from '@alfresco/adf-core';
import { ClassesApi, Node } from '@alfresco/js-api';
import { TestBed } from '@angular/core/testing';
import { ContentMetadataService } from './content-metadata.service';
@@ -24,6 +24,7 @@ import { PropertyGroup } from '../interfaces/property-group.interface';
import { TranslateModule } from '@ngx-translate/core';
import { ContentTypePropertiesService } from './content-type-property.service';
import { ContentTestingModule } from '../../testing/content.testing.module';
import { PropertyDescriptorsService } from './property-descriptors.service';
describe('ContentMetaDataService', () => {
@@ -67,8 +68,8 @@ describe('ContentMetaDataService', () => {
beforeEach(() => {
service = TestBed.inject(ContentMetadataService);
contentPropertyService = TestBed.inject(ContentTypePropertiesService);
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
classesApi = alfrescoApiService.classesApi;
const propertyDescriptorsService = TestBed.inject(PropertyDescriptorsService);
classesApi = propertyDescriptorsService['classesApi'];
appConfig = TestBed.inject(AppConfigService);
});
@@ -17,7 +17,7 @@
import { TestBed } from '@angular/core/testing';
import { PropertyDescriptorsService } from './property-descriptors.service';
import { AlfrescoApiService, setupTestBed } from '@alfresco/adf-core';
import { setupTestBed } from '@alfresco/adf-core';
import { ClassesApi } from '@alfresco/js-api';
import { PropertyGroup } from '../interfaces/content-metadata.interfaces';
import { ContentTestingModule } from '../../testing/content.testing.module';
@@ -37,8 +37,7 @@ describe('PropertyDescriptorLoaderService', () => {
beforeEach(() => {
service = TestBed.inject(PropertyDescriptorsService);
const alfrescoApiService = TestBed.inject(AlfrescoApiService);
classesApi = alfrescoApiService.classesApi;
classesApi = service['classesApi'];
});
it('should load the groups passed by paramter', () => {
@@ -20,18 +20,22 @@ import { AlfrescoApiService } from '@alfresco/adf-core';
import { Observable, defer, forkJoin } from 'rxjs';
import { PropertyGroup, PropertyGroupContainer } from '../interfaces/content-metadata.interfaces';
import { map } from 'rxjs/operators';
import { ClassesApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
})
export class PropertyDescriptorsService {
private classesApi: ClassesApi;
constructor(private alfrescoApiService: AlfrescoApiService) {}
constructor(private alfrescoApiService: AlfrescoApiService) {
this.classesApi = new ClassesApi(this.alfrescoApiService.getInstance());
}
load(groupNames: string[]): Observable<PropertyGroupContainer> {
const groupFetchStreams = groupNames
.map((groupName) => groupName.replace(':', '_'))
.map((groupName) => defer( () => this.alfrescoApiService.classesApi.getClass(groupName)) );
.map((groupName) => defer(() => this.classesApi.getClass(groupName)));
return forkJoin(groupFetchStreams).pipe(
map(this.convertToObject)
@@ -17,7 +17,7 @@
import { Directive, Input, HostListener, OnChanges, NgZone, OnDestroy } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { NodeEntry, Node } from '@alfresco/js-api';
import { NodeEntry, NodesApi } from '@alfresco/js-api';
import { ShareDialogComponent } from './content-node-share.dialog';
import { Observable, from, Subject } from 'rxjs';
@@ -43,11 +43,13 @@ export class NodeSharedDirective implements OnChanges, OnDestroy {
baseShareUrl: string;
private onDestroy$ = new Subject<boolean>();
private nodesApi = new NodesApi();
constructor(
private dialog: MatDialog,
private zone: NgZone,
private alfrescoApiService: AlfrescoApiService) {
this.nodesApi = new NodesApi(this.alfrescoApiService.getInstance());
}
ngOnDestroy() {
@@ -61,8 +63,8 @@ export class NodeSharedDirective implements OnChanges, OnDestroy {
const nodeId = nodeEntry.entry['nodeId'] || nodeEntry.entry['guid'];
if (nodeId) {
this.getNodeInfo(nodeId).subscribe((entry) => {
this.openShareLinkDialog({ entry });
this.getNodeInfo(nodeId).subscribe((node) => {
this.openShareLinkDialog(node);
});
} else {
this.openShareLinkDialog(nodeEntry);
@@ -70,13 +72,13 @@ export class NodeSharedDirective implements OnChanges, OnDestroy {
}
}
private getNodeInfo(nodeId: string): Observable<Node> {
private getNodeInfo(nodeId: string): Observable<NodeEntry> {
const options = {
include: ['allowableOperations']
include: ['allowableOperations']
};
return from(this.alfrescoApiService.nodesApi.getNodeInfo(nodeId, options));
}
return from(this.nodesApi.getNode(nodeId, options));
}
private openShareLinkDialog(node: NodeEntry) {
this.dialog.open(ShareDialogComponent, {
@@ -1,69 +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 { TypeEntry } from '@alfresco/js-api';
import { AlfrescoApiService } from 'core';
import { of } from 'rxjs';
import { ContentTypeService } from './content-type.service';
describe('ContentTypeService', () => {
const fakeEntryMock: TypeEntry = {
entry: {
id : 'fake-type-id',
title: 'fake-title',
description: 'optional-fake-description',
parentId: 'cm:parent',
properties: []
}
};
const mockTypesApi = jasmine.createSpyObj('TypesApi', ['getType', 'listTypes']);
const alfrescoApiService: AlfrescoApiService = new AlfrescoApiService(null, null);
const contentTypeService: ContentTypeService = new ContentTypeService(alfrescoApiService);
beforeEach(() => {
spyOnProperty(alfrescoApiService, 'typesApi').and.returnValue(mockTypesApi);
});
it('should get a node type info', (done) => {
mockTypesApi.getType.and.returnValue(of(fakeEntryMock));
contentTypeService.getContentTypeByPrefix('whatever-whenever').subscribe((result) => {
expect(result).toBeDefined();
expect(result).not.toBeNull();
expect(result.entry.id).toBe('fake-type-id');
expect(mockTypesApi.getType).toHaveBeenCalledWith('whatever-whenever');
done();
});
});
it('should get the list of children types', (done) => {
mockTypesApi.listTypes.and.returnValue(of({ list: {entries: [fakeEntryMock]}}));
contentTypeService.getContentTypeChildren('whatever-whenever').subscribe((results: TypeEntry[]) => {
expect(results).toBeDefined();
expect(results).not.toBeNull();
expect(results.length).toBe(1);
expect(results[0].entry.id).toBe('fake-type-id');
expect(mockTypesApi.listTypes).toHaveBeenCalledWith({
where: '(parentId in (\'whatever-whenever\') and not namespaceUri matches(\'http://www.alfresco.*\'))',
include: [ 'properties']
});
done();
});
});
});
@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { TypeEntry, TypePaging } from '@alfresco/js-api';
import { TypeEntry, TypePaging, TypesApi } from '@alfresco/js-api';
import { Injectable } from '@angular/core';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { from, Observable } from 'rxjs';
@@ -25,11 +25,14 @@ import { map } from 'rxjs/operators';
})
export class ContentTypeService {
private typesApi: TypesApi;
constructor(private alfrescoApiService: AlfrescoApiService) {
this.typesApi = new TypesApi(this.alfrescoApiService.getInstance());
}
getContentTypeByPrefix(prefixedType: string): Observable<TypeEntry> {
return from(this.alfrescoApiService.typesApi.getType(prefixedType));
return from(this.typesApi.getType(prefixedType));
}
getContentTypeChildren(nodeType: string): Observable<TypeEntry[]> {
@@ -38,7 +41,7 @@ export class ContentTypeService {
where,
include: ['properties']
};
return from(this.alfrescoApiService.typesApi.listTypes(opts)).pipe(
return from(this.typesApi.listTypes(opts)).pipe(
map((result: TypePaging) => result.list.entries)
);
}
@@ -19,7 +19,7 @@ import { LibraryDialogComponent } from './library.dialog';
import { TestBed, fakeAsync, tick, flush, ComponentFixture, flushMicrotasks } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
import { AlfrescoApiService, setupTestBed, SitesService } from '@alfresco/adf-core';
import { setupTestBed, SitesService } from '@alfresco/adf-core';
import { ContentTestingModule } from '../../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { of, throwError } from 'rxjs';
@@ -30,7 +30,6 @@ describe('LibraryDialogComponent', () => {
let fixture: ComponentFixture<LibraryDialogComponent>;
let component: LibraryDialogComponent;
let sitesService: SitesService;
let alfrescoApi;
let findSitesSpy;
const findSitesResponse = { list: { entries: [] } };
const dialogRef = {
@@ -51,9 +50,8 @@ describe('LibraryDialogComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(LibraryDialogComponent);
component = fixture.componentInstance;
alfrescoApi = TestBed.inject(AlfrescoApiService);
sitesService = TestBed.inject(SitesService);
findSitesSpy = spyOn(alfrescoApi.getInstance().core.queriesApi, 'findSites');
findSitesSpy = spyOn(component['queriesApi'], 'findSites');
});
afterEach(() => {
@@ -17,265 +17,267 @@
import { Observable, Subject } from 'rxjs';
import {
Component,
OnInit,
Output,
EventEmitter,
OnDestroy,
ViewEncapsulation
Component,
OnInit,
Output,
EventEmitter,
OnDestroy,
ViewEncapsulation
} from '@angular/core';
import {
FormBuilder,
FormGroup,
Validators,
FormControl,
AbstractControl
FormBuilder,
FormGroup,
Validators,
FormControl,
AbstractControl
} from '@angular/forms';
import { MatDialogRef } from '@angular/material/dialog';
import { SiteBodyCreate, SiteEntry, SitePaging } from '@alfresco/js-api';
import { QueriesApi, SiteBodyCreate, SiteEntry, SitePaging } from '@alfresco/js-api';
import { AlfrescoApiService, SitesService } from '@alfresco/adf-core';
import { debounceTime, finalize, mergeMap, takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-library-dialog',
styleUrls: ['./library.dialog.scss'],
templateUrl: './library.dialog.html',
encapsulation: ViewEncapsulation.None,
host: { class: 'adf-library-dialog' }
selector: 'adf-library-dialog',
styleUrls: ['./library.dialog.scss'],
templateUrl: './library.dialog.html',
encapsulation: ViewEncapsulation.None,
host: { class: 'adf-library-dialog' }
})
export class LibraryDialogComponent implements OnInit, OnDestroy {
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when the new library is created successfully. The
* event parameter is a SiteEntry object with the details of the
* newly-created library.
*/
@Output()
success: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when the new library is created successfully. The
* event parameter is a SiteEntry object with the details of the
* newly-created library.
*/
@Output()
success: EventEmitter<any> = new EventEmitter<any>();
onDestroy$: Subject<boolean> = new Subject<boolean>();
onDestroy$: Subject<boolean> = new Subject<boolean>();
createTitle = 'LIBRARY.DIALOG.CREATE_TITLE';
libraryTitleExists = false;
form: FormGroup;
visibilityOption: any;
visibilityOptions = [
{ value: 'PUBLIC', label: 'LIBRARY.VISIBILITY.PUBLIC', disabled: false },
{ value: 'PRIVATE', label: 'LIBRARY.VISIBILITY.PRIVATE', disabled: false },
{
value: 'MODERATED',
label: 'LIBRARY.VISIBILITY.MODERATED',
disabled: false
}
];
disableCreateButton = false;
constructor(
private alfrescoApiService: AlfrescoApiService,
private sitesService: SitesService,
private formBuilder: FormBuilder,
private dialog: MatDialogRef<LibraryDialogComponent>
) {}
ngOnInit() {
const validators = {
id: [
Validators.required,
Validators.maxLength(72),
this.forbidSpecialCharacters
],
title: [
Validators.required,
this.forbidOnlySpaces,
Validators.minLength(2),
Validators.maxLength(256)
],
description: [Validators.maxLength(512)]
};
this.form = this.formBuilder.group({
title: [null, validators.title],
id: [null, validators.id, this.createSiteIdValidator()],
description: ['', validators.description]
});
this.visibilityOption = this.visibilityOptions[0].value;
this.form.controls['title'].valueChanges
.pipe(
debounceTime(500),
mergeMap(
(title) => this.checkLibraryNameExists(title),
(title) => title
),
takeUntil(this.onDestroy$)
)
.subscribe((title: string) => {
if (!this.form.controls['id'].dirty && this.canGenerateId(title)) {
this.form.patchValue({ id: this.sanitize(title.trim()) });
this.form.controls['id'].markAsTouched();
createTitle = 'LIBRARY.DIALOG.CREATE_TITLE';
libraryTitleExists = false;
form: FormGroup;
visibilityOption: any;
visibilityOptions = [
{ value: 'PUBLIC', label: 'LIBRARY.VISIBILITY.PUBLIC', disabled: false },
{ value: 'PRIVATE', label: 'LIBRARY.VISIBILITY.PRIVATE', disabled: false },
{
value: 'MODERATED',
label: 'LIBRARY.VISIBILITY.MODERATED',
disabled: false
}
});
}
];
disableCreateButton = false;
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
queriesApi: QueriesApi;
get title(): string {
const { title } = this.form.value;
return (title || '').trim();
}
get id(): string {
const { id } = this.form.value;
return (id || '').trim();
}
get description(): string {
const { description } = this.form.value;
return (description || '').trim();
}
get visibility(): string {
return this.visibilityOption || '';
}
submit() {
const { form, dialog } = this;
if (!form.valid) {
return;
constructor(
private alfrescoApiService: AlfrescoApiService,
private sitesService: SitesService,
private formBuilder: FormBuilder,
private dialog: MatDialogRef<LibraryDialogComponent>
) {
this.queriesApi = new QueriesApi(this.alfrescoApiService.getInstance());
}
this.disableCreateButton = true;
this.create().pipe(finalize(() => this.disableCreateButton = false)).subscribe(
(node: SiteEntry) => {
this.success.emit(node);
dialog.close(node);
},
(error) => this.handleError(error)
);
}
visibilityChangeHandler(event) {
this.visibilityOption = event.value;
}
private create(): Observable<SiteEntry> {
const { title, id, description, visibility } = this;
const siteBody = <SiteBodyCreate> {
id,
title,
description,
visibility
};
return this.sitesService.createSite(siteBody);
}
private sanitize(input: string) {
return input.replace(/[\s\s]+/g, '-').replace(/[^A-Za-z0-9-]/g, '');
}
private canGenerateId(title) {
return Boolean(title.replace(/[^A-Za-z0-9-]/g, '').length);
}
private handleError(error: any): any {
try {
const {
error: { statusCode }
} = JSON.parse(error.message);
if (statusCode === 409) {
this.form.controls['id'].setErrors({
message: 'LIBRARY.ERRORS.CONFLICT'
});
}
} catch (error) {
}
return error;
}
private async checkLibraryNameExists(libraryTitle: string) {
let entries = [];
try {
entries = (await this.findLibraryByTitle(libraryTitle)).list.entries;
} catch {
entries = [];
}
if (entries.length) {
this.libraryTitleExists = entries[0].entry.title.toLowerCase() === libraryTitle.toLowerCase();
} else {
this.libraryTitleExists = false;
}
}
private findLibraryByTitle(libraryTitle: string): Promise<SitePaging> {
return this.alfrescoApiService
.getInstance()
.core.queriesApi.findSites(libraryTitle, {
maxItems: 1,
fields: ['title']
});
}
private forbidSpecialCharacters({ value }: FormControl) {
if (value === null || value.length === 0) {
return null;
}
const validCharacters: RegExp = /[^A-Za-z0-9-]/;
const isValid: boolean = !validCharacters.test(value);
return isValid
? null
: {
message: 'LIBRARY.ERRORS.ILLEGAL_CHARACTERS'
ngOnInit() {
const validators = {
id: [
Validators.required,
Validators.maxLength(72),
this.forbidSpecialCharacters
],
title: [
Validators.required,
this.forbidOnlySpaces,
Validators.minLength(2),
Validators.maxLength(256)
],
description: [Validators.maxLength(512)]
};
}
private forbidOnlySpaces({ value }: FormControl) {
if (value === null || value.length === 0) {
return null;
this.form = this.formBuilder.group({
title: [null, validators.title],
id: [null, validators.id, this.createSiteIdValidator()],
description: ['', validators.description]
});
this.visibilityOption = this.visibilityOptions[0].value;
this.form.controls['title'].valueChanges
.pipe(
debounceTime(500),
mergeMap(
(title) => this.checkLibraryNameExists(title),
(title) => title
),
takeUntil(this.onDestroy$)
)
.subscribe((title: string) => {
if (!this.form.controls['id'].dirty && this.canGenerateId(title)) {
this.form.patchValue({ id: this.sanitize(title.trim()) });
this.form.controls['id'].markAsTouched();
}
});
}
const isValid: boolean = !!(value || '').trim();
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
return isValid
? null
: {
message: 'LIBRARY.ERRORS.ONLY_SPACES'
get title(): string {
const { title } = this.form.value;
return (title || '').trim();
}
get id(): string {
const { id } = this.form.value;
return (id || '').trim();
}
get description(): string {
const { description } = this.form.value;
return (description || '').trim();
}
get visibility(): string {
return this.visibilityOption || '';
}
submit() {
const { form, dialog } = this;
if (!form.valid) {
return;
}
this.disableCreateButton = true;
this.create().pipe(finalize(() => this.disableCreateButton = false)).subscribe(
(node: SiteEntry) => {
this.success.emit(node);
dialog.close(node);
},
(error) => this.handleError(error)
);
}
visibilityChangeHandler(event) {
this.visibilityOption = event.value;
}
private create(): Observable<SiteEntry> {
const { title, id, description, visibility } = this;
const siteBody = <SiteBodyCreate> {
id,
title,
description,
visibility
};
}
private createSiteIdValidator() {
let timer;
return this.sitesService.createSite(siteBody);
}
return (control: AbstractControl) => {
if (timer) {
clearTimeout(timer);
}
private sanitize(input: string) {
return input.replace(/[\s\s]+/g, '-').replace(/[^A-Za-z0-9-]/g, '');
}
return new Promise((resolve) => {
timer = setTimeout(() => {
return this.sitesService.getSite(control.value).subscribe(
() => resolve({ message: 'LIBRARY.ERRORS.EXISTENT_SITE' }),
() => resolve(null)
);
}, 300);
});
};
}
private canGenerateId(title) {
return Boolean(title.replace(/[^A-Za-z0-9-]/g, '').length);
}
private handleError(error: any): any {
try {
const {
error: { statusCode }
} = JSON.parse(error.message);
if (statusCode === 409) {
this.form.controls['id'].setErrors({
message: 'LIBRARY.ERRORS.CONFLICT'
});
}
} catch (error) {
}
return error;
}
private async checkLibraryNameExists(libraryTitle: string) {
let entries = [];
try {
entries = (await this.findLibraryByTitle(libraryTitle)).list.entries;
} catch {
entries = [];
}
if (entries.length) {
this.libraryTitleExists = entries[0].entry.title.toLowerCase() === libraryTitle.toLowerCase();
} else {
this.libraryTitleExists = false;
}
}
private findLibraryByTitle(libraryTitle: string): Promise<SitePaging> {
return this.queriesApi.findSites(libraryTitle, {
maxItems: 1,
fields: ['title']
});
}
private forbidSpecialCharacters({ value }: FormControl) {
if (value === null || value.length === 0) {
return null;
}
const validCharacters: RegExp = /[^A-Za-z0-9-]/;
const isValid: boolean = !validCharacters.test(value);
return isValid
? null
: {
message: 'LIBRARY.ERRORS.ILLEGAL_CHARACTERS'
};
}
private forbidOnlySpaces({ value }: FormControl) {
if (value === null || value.length === 0) {
return null;
}
const isValid: boolean = !!(value || '').trim();
return isValid
? null
: {
message: 'LIBRARY.ERRORS.ONLY_SPACES'
};
}
private createSiteIdValidator() {
let timer;
return (control: AbstractControl) => {
if (timer) {
clearTimeout(timer);
}
return new Promise((resolve) => {
timer = setTimeout(() => {
return this.sitesService.getSite(control.value).subscribe(
() => resolve({ message: 'LIBRARY.ERRORS.EXISTENT_SITE' }),
() => resolve(null)
);
}, 300);
});
};
}
}
@@ -19,8 +19,7 @@ import moment from 'moment-es6';
import { TestBed, fakeAsync, tick, ComponentFixture } from '@angular/core/testing';
import { MatDialogRef } from '@angular/material/dialog';
import { AlfrescoApiService, setupTestBed } from '@alfresco/adf-core';
import { NodeBodyLock } from '@alfresco/js-api';
import { setupTestBed } from '@alfresco/adf-core';
import { NodeLockDialogComponent } from './node-lock.dialog';
import { ContentTestingModule } from '../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
@@ -29,7 +28,6 @@ describe('NodeLockDialogComponent', () => {
let fixture: ComponentFixture<NodeLockDialogComponent>;
let component: NodeLockDialogComponent;
let alfrescoApi: AlfrescoApiService;
let expiryDate;
const dialogRef = {
close: jasmine.createSpy('close')
@@ -48,7 +46,6 @@ describe('NodeLockDialogComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(NodeLockDialogComponent);
component = fixture.componentInstance;
alfrescoApi = TestBed.inject(AlfrescoApiService);
});
afterEach(() => {
@@ -98,33 +95,9 @@ describe('NodeLockDialogComponent', () => {
expect(component.form.value.time.format()).toBe(newTime.format());
});
it('should submit the form and lock the node', () => {
spyOn(alfrescoApi.nodesApi, 'lockNode').and.returnValue(Promise.resolve(null));
component.submit();
expect(alfrescoApi.nodesApi.lockNode).toHaveBeenCalledWith(
'node-id',
new NodeBodyLock({
'timeToExpire': 60,
'type': 'ALLOW_OWNER_CHANGES',
'lifetime': 'PERSISTENT'
})
);
});
it('should submit the form and unlock the node', () => {
spyOn(alfrescoApi.nodesApi, 'unlockNode').and.returnValue(Promise.resolve(null));
component.form.controls['isLocked'].setValue(false);
component.submit();
expect(alfrescoApi.nodesApi.unlockNode).toHaveBeenCalledWith('node-id');
});
it('should call dialog to close with form data when submit is successfully', fakeAsync(() => {
const node: any = { entry: {} };
spyOn(alfrescoApi.nodesApi, 'lockNode').and.returnValue(Promise.resolve(node));
spyOn(component['nodesApi'], 'lockNode').and.returnValue(Promise.resolve(node));
component.submit();
tick();
@@ -134,7 +107,7 @@ describe('NodeLockDialogComponent', () => {
}));
it('should call onError if submit fails', fakeAsync(() => {
spyOn(alfrescoApi.nodesApi, 'lockNode').and.returnValue(Promise.reject('error'));
spyOn(component['nodesApi'], 'lockNode').and.returnValue(Promise.reject('error'));
spyOn(component.data, 'onError');
component.submit();
@@ -21,7 +21,7 @@ import { Component, Inject, OnInit, Optional, ViewEncapsulation } from '@angular
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FormBuilder, FormGroup } from '@angular/forms';
import { NodeBodyLock, Node, NodeEntry } from '@alfresco/js-api';
import { NodeBodyLock, Node, NodeEntry, NodesApi } from '@alfresco/js-api';
import { AlfrescoApiService } from '@alfresco/adf-core';
@Component({
@@ -35,6 +35,8 @@ export class NodeLockDialogComponent implements OnInit {
node: Node = null;
nodeName: string;
private nodesApi: NodesApi;
constructor(
private formBuilder: FormBuilder,
public dialog: MatDialogRef<NodeLockDialogComponent>,
@@ -43,6 +45,7 @@ export class NodeLockDialogComponent implements OnInit {
@Inject(MAT_DIALOG_DATA)
public data: any
) {
this.nodesApi = new NodesApi(this.alfrescoApi.getInstance());
}
ngOnInit() {
@@ -75,13 +78,13 @@ export class NodeLockDialogComponent implements OnInit {
}
private toggleLock(): Promise<NodeEntry> {
const { alfrescoApi: { nodesApi }, data: { node } } = this;
const { data: { node } } = this;
if (this.form.value.isLocked) {
return nodesApi.lockNode(node.id, this.nodeBodyLock);
return this.nodesApi.lockNode(node.id, this.nodeBodyLock);
}
return nodesApi.unlockNode(node.id);
return this.nodesApi.unlockNode(node.id);
}
submit(): void {
@@ -103,7 +103,7 @@ describe('DocumentList', () => {
spyFolder = spyOn(documentListService, 'getFolder').and.returnValue(of({ list: {} }));
spyFolderNode = spyOn(documentListService, 'getFolderNode').and.returnValue(of(new NodeEntry({ entry: {} })));
spyOn(apiService.nodesApi, 'getNode').and.returnValue(Promise.resolve(new NodeEntry({ entry: {} })));
spyOn(documentList['nodesApi'], 'getNode').and.returnValue(Promise.resolve(new NodeEntry({ entry: {} })));
documentList.ngOnInit();
documentList.currentFolderId = 'no-node';
@@ -48,7 +48,7 @@ import {
DataRow
} from '@alfresco/adf-core';
import { Node, NodeEntry, NodePaging, Pagination } from '@alfresco/js-api';
import { Node, NodeEntry, NodePaging, NodesApi, Pagination } from '@alfresco/js-api';
import { Subject, BehaviorSubject, of } from 'rxjs';
import { ShareDataRow } from './../data/share-data-row.model';
import { ShareDataTableAdapter } from './../data/share-datatable-adapter';
@@ -342,6 +342,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
private rowMenuCache: { [key: string]: ContentActionModel[] } = {};
private loadingTimeout;
private onDestroy$ = new Subject<boolean>();
private nodesApi: NodesApi;
constructor(private documentListService: DocumentListService,
private ngZone: NgZone,
@@ -352,6 +353,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
private thumbnailService: ThumbnailService,
private alfrescoApiService: AlfrescoApiService,
private lockService: LockService) {
this.nodesApi = new NodesApi(this.alfrescoApiService.getInstance());
this.userPreferencesService
.select(UserPreferenceValues.PaginationSize)
.pipe(takeUntil(this.onDestroy$))
@@ -801,7 +803,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
include: this.includeFields
};
this.alfrescoApiService.nodesApi.getNode(nodeEntry.entry['guid'], options)
this.nodesApi.getNode(nodeEntry.entry['guid'], options)
.then((node: NodeEntry) => {
this.navigateTo(node.entry);
});
@@ -41,46 +41,22 @@ export class CustomResourcesService {
private CREATE_PERMISSION = 'create';
private _peopleApi: PeopleApi;
private _sitesApi: SitesApi;
private _trashcanApi: TrashcanApi;
private _searchApi: SearchApi;
private _sharedLinksApi: SharedlinksApi;
private _favoritesApi: FavoritesApi;
private _nodesApi: NodesApi;
peopleApi: PeopleApi;
sitesApi: SitesApi;
trashcanApi: TrashcanApi;
searchApi: SearchApi;
sharedLinksApi: SharedlinksApi;
favoritesApi: FavoritesApi;
nodesApi: NodesApi;
constructor(private apiService: AlfrescoApiService, private logService: LogService) {}
private get api() {
return this.apiService.getInstance();
}
get peopleApi(): PeopleApi {
return this._peopleApi || (this._peopleApi = new PeopleApi(this.api));
}
get sitesApi(): SitesApi {
return this._sitesApi || (this._sitesApi = new SitesApi(this.api));
}
get searchApi(): SearchApi {
return this._searchApi || (this._searchApi = new SearchApi(this.api));
}
get favoritesApi(): FavoritesApi {
return this._favoritesApi || (this._favoritesApi = new FavoritesApi(this.api));
}
get sharedLinksApi(): SharedlinksApi {
return this._sharedLinksApi || (this._sharedLinksApi = new SharedlinksApi(this.api));
}
get trashcanApi(): TrashcanApi {
return this._trashcanApi || (this._trashcanApi = new TrashcanApi(this.api));
}
get nodesApi(): NodesApi {
return this._nodesApi || (this._nodesApi = new NodesApi(this.api));
constructor(private apiService: AlfrescoApiService, private logService: LogService) {
this.peopleApi = new PeopleApi(this.apiService.getInstance());
this.sitesApi = new SitesApi(this.apiService.getInstance());
this.favoritesApi = new FavoritesApi(this.apiService.getInstance());
this.searchApi = new SearchApi(this.apiService.getInstance());
this.sharedLinksApi = new SharedlinksApi(this.apiService.getInstance());
this.trashcanApi = new TrashcanApi(this.apiService.getInstance());
this.nodesApi = new NodesApi(this.apiService.getInstance());
}
/**
@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { AlfrescoApiService, setupTestBed } from '@alfresco/adf-core';
import { setupTestBed } from '@alfresco/adf-core';
import { DocumentListService } from './document-list.service';
import { TestBed } from '@angular/core/testing';
import { ContentTestingModule } from '../../testing/content.testing.module';
@@ -26,7 +26,6 @@ declare let jasmine: any;
describe('DocumentListService', () => {
let service: DocumentListService;
let alfrescoApiService: AlfrescoApiService;
const fakeFolder = {
'list': {
@@ -70,7 +69,6 @@ describe('DocumentListService', () => {
});
beforeEach(() => {
alfrescoApiService = TestBed.inject(AlfrescoApiService);
service = TestBed.inject(DocumentListService);
jasmine.Ajax.install();
});
@@ -99,7 +97,7 @@ describe('DocumentListService', () => {
});
it('should add the includeTypes in the request Node Children if required', () => {
const spyGetNodeInfo = spyOn(alfrescoApiService.getInstance().nodes, 'getNodeChildren').and.callThrough();
const spyGetNodeInfo = spyOn(service['nodes'], 'listNodeChildren').and.callThrough();
service.getFolder('/fake-root/fake-name', {}, ['isLocked']);
@@ -111,7 +109,7 @@ describe('DocumentListService', () => {
});
it('should not add the includeTypes in the request Node Children if is duplicated', () => {
const spyGetNodeInfo = spyOn(alfrescoApiService.getInstance().nodes, 'getNodeChildren').and.callThrough();
const spyGetNodeInfo = spyOn(service['nodes'], 'listNodeChildren').and.callThrough();
service.getFolder('/fake-root/fake-name', {}, ['allowableOperations']);
@@ -123,7 +121,7 @@ describe('DocumentListService', () => {
});
it('should add the includeTypes in the request getFolderNode if required', () => {
const spyGetNodeInfo = spyOn(alfrescoApiService.getInstance().nodes, 'getNode').and.callThrough();
const spyGetNodeInfo = spyOn(service['nodes'], 'getNode').and.callThrough();
service.getFolderNode('test-id', ['isLocked']);
@@ -134,7 +132,7 @@ describe('DocumentListService', () => {
});
it('should not add the includeTypes in the request getFolderNode if is duplicated', () => {
const spyGetNodeInfo = spyOn(alfrescoApiService.getInstance().nodes, 'getNode').and.callThrough();
const spyGetNodeInfo = spyOn(service['nodes'], 'getNode').and.callThrough();
service.getFolderNode('test-id', ['allowableOperations']);
@@ -20,7 +20,7 @@ import {
} from '@alfresco/adf-core';
import { Injectable } from '@angular/core';
import { NodeEntry, NodePaging } from '@alfresco/js-api';
import { NodeEntry, NodePaging, NodesApi } from '@alfresco/js-api';
import { DocumentLoaderNode } from '../models/document-folder.model';
import { Observable, from, throwError, forkJoin } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
@@ -34,10 +34,13 @@ export class DocumentListService implements DocumentListLoader {
static ROOT_ID = '-root-';
nodes: NodesApi;
constructor(private contentService: ContentService,
private apiService: AlfrescoApiService,
private logService: LogService,
private customResourcesService: CustomResourcesService) {
this.nodes = new NodesApi(this.apiService.getInstance());
}
/**
@@ -46,7 +49,7 @@ export class DocumentListService implements DocumentListLoader {
* @returns Empty response when the operation is complete
*/
deleteNode(nodeId: string): Observable<any> {
return from(this.apiService.getInstance().nodes.deleteNode(nodeId));
return from(this.nodes.deleteNode(nodeId));
}
/**
@@ -57,7 +60,7 @@ export class DocumentListService implements DocumentListLoader {
* @returns NodeEntry for the copied node
*/
copyNode(nodeId: string, targetParentId: string): Observable<NodeEntry> {
return from(this.apiService.getInstance().nodes.copyNode(nodeId, { targetParentId })).pipe(
return from(this.nodes.copyNode(nodeId, { targetParentId })).pipe(
catchError((err) => this.handleError(err))
);
}
@@ -70,7 +73,7 @@ export class DocumentListService implements DocumentListLoader {
* @returns NodeEntry for the moved node
*/
moveNode(nodeId: string, targetParentId: string): Observable<NodeEntry> {
return from(this.apiService.getInstance().nodes.moveNode(nodeId, { targetParentId })).pipe(
return from(this.nodes.moveNode(nodeId, { targetParentId })).pipe(
catchError((err) => this.handleError(err))
);
}
@@ -115,7 +118,7 @@ export class DocumentListService implements DocumentListLoader {
}
}
return from(this.apiService.getInstance().nodes.getNodeChildren(rootNodeId, params)).pipe(
return from(this.nodes.listNodeChildren(rootNodeId, params)).pipe(
catchError((err) => this.handleError(err))
);
}
@@ -153,7 +156,7 @@ export class DocumentListService implements DocumentListLoader {
include: includeFieldsRequest
};
return from(this.apiService.getInstance().nodes.getNode(nodeId, opts)).pipe(
return from(this.nodes.getNode(nodeId, opts)).pipe(
catchError((err) => this.handleError(err))
);
}
@@ -16,19 +16,24 @@
*/
import { Injectable } from '@angular/core';
import { GroupEntry } from '@alfresco/js-api';
import { GroupEntry, GroupsApi } from '@alfresco/js-api';
import { AlfrescoApiService } from '@alfresco/adf-core';
@Injectable({
providedIn: 'root'
})
export class GroupService {
groupsApi: GroupsApi;
constructor(
private alfrescoApiService: AlfrescoApiService
) {}
) {
this.groupsApi = new GroupsApi(this.alfrescoApiService.getInstance());
}
async listAllGroupMembershipsForPerson(personId: string, opts?: any, accumulator = []): Promise<GroupEntry[]> {
const groupsPaginated = await this.alfrescoApiService.groupsApi.listGroupMembershipsForPerson(personId, opts);
const groupsPaginated = await this.groupsApi.listGroupMembershipsForPerson(personId, opts);
accumulator = [...accumulator, ...groupsPaginated.list.entries];
if (groupsPaginated.list.pagination.hasMoreItems) {
const skip = groupsPaginated.list.pagination.skipCount + groupsPaginated.list.pagination.count;
@@ -15,8 +15,22 @@
* limitations under the License.
*/
import { AlfrescoApiService, NodesApiService, SearchService, TranslationService, EcmUserModel } from '@alfresco/adf-core';
import { Group, GroupMemberEntry, GroupMemberPaging, Node, PathElement, PermissionElement, QueryBody } from '@alfresco/js-api';
import {
AlfrescoApiService,
NodesApiService,
SearchService,
TranslationService,
EcmUserModel
} from '@alfresco/adf-core';
import {
Group,
GroupMemberEntry,
GroupMemberPaging, GroupsApi,
Node,
PathElement,
PermissionElement,
QueryBody
} from '@alfresco/js-api';
import { Injectable } from '@angular/core';
import { forkJoin, from, Observable, of, throwError } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
@@ -28,10 +42,13 @@ import { RoleModel } from '../models/role.model';
})
export class NodePermissionService {
groupsApi: GroupsApi;
constructor(private apiService: AlfrescoApiService,
private searchApiService: SearchService,
private nodeService: NodesApiService,
private translation: TranslationService) {
this.groupsApi = new GroupsApi(this.apiService.getInstance());
}
/**
@@ -44,7 +61,7 @@ export class NodePermissionService {
return this.searchApiService.searchByQueryBody(retrieveSiteQueryBody)
.pipe(
switchMap((siteNodeList: any) => {
if ( siteNodeList.list.entries.length > 0 ) {
if (siteNodeList.list.entries.length > 0) {
const siteName = siteNodeList.list.entries[0].entry.name;
return this.getGroupMembersBySiteName(siteName);
} else {
@@ -80,7 +97,7 @@ export class NodePermissionService {
* @returns Node with updated permission
*/
updatePermissionRole(node: Node, updatedPermissionRole: PermissionElement): Observable<Node> {
const permissionBody = { permissions: { locallySet: []} };
const permissionBody = { permissions: { locallySet: [] } };
const index = node.permissions.locallySet.map((permission) => permission.authorityId).indexOf(updatedPermissionRole.authorityId);
permissionBody.permissions.locallySet = permissionBody.permissions.locallySet.concat(node.permissions.locallySet);
if (index !== -1) {
@@ -98,7 +115,7 @@ export class NodePermissionService {
* @returns Node with updated permissions
*/
updateNodePermissions(nodeId: string, permissionList: PermissionElement[]): Observable<Node> {
return this.nodeService.getNode(nodeId).pipe(
return this.nodeService.getNode(nodeId).pipe(
switchMap((node) => this.updateLocallySetPermissions(node, permissionList))
);
}
@@ -110,12 +127,12 @@ export class NodePermissionService {
* @returns Node with updated permissions
*/
updateLocallySetPermissions(node: Node, permissions: PermissionElement[]): Observable<Node> {
const permissionBody = { permissions: { locallySet: []} };
const permissionBody = { permissions: { locallySet: [] } };
const permissionList = permissions;
const duplicatedPermissions = this.getDuplicatedPermissions(node.permissions.locallySet, permissionList);
if (duplicatedPermissions.length > 0) {
const list = duplicatedPermissions.map((permission) => 'authority -> ' + permission.authorityId + ' / role -> ' + permission.name).join(', ');
const duplicatePermissionMessage: string = this.translation.instant('PERMISSION_MANAGER.ERROR.DUPLICATE-PERMISSION', {list});
const duplicatePermissionMessage: string = this.translation.instant('PERMISSION_MANAGER.ERROR.DUPLICATE-PERMISSION', { list });
return throwError(duplicatePermissionMessage);
}
permissionBody.permissions.locallySet = node.permissions.locallySet ? node.permissions.locallySet.concat(permissionList) : permissionList;
@@ -137,8 +154,8 @@ export class NodePermissionService {
private isEqualPermission(oldPermission: PermissionElement, newPermission: PermissionElement): boolean {
return oldPermission.accessStatus === newPermission.accessStatus &&
oldPermission.authorityId === newPermission.authorityId &&
oldPermission.name === newPermission.name;
oldPermission.authorityId === newPermission.authorityId &&
oldPermission.name === newPermission.name;
}
/**
@@ -181,7 +198,7 @@ export class NodePermissionService {
* @returns List of members
*/
getGroupMemberByGroupName(groupName: string, opts?: any): Observable<GroupMemberPaging> {
return from(this.apiService.groupsApi.listGroupMemberships(groupName, opts));
return from(this.groupsApi.listGroupMemberships(groupName, opts));
}
private formattedRoleName(displayName, siteName): string {
@@ -245,10 +262,10 @@ export class NodePermissionService {
const permissionBody = { permissions: { locallySet: [] } };
permissions.forEach((permission) => {
const index = node.permissions.locallySet.findIndex((locallySet) => locallySet.authorityId === permission.authorityId);
if (index !== -1) {
node.permissions.locallySet.splice(index, 1);
}
const index = node.permissions.locallySet.findIndex((locallySet) => locallySet.authorityId === permission.authorityId);
if (index !== -1) {
node.permissions.locallySet.splice(index, 1);
}
});
permissionBody.permissions.locallySet = node.permissions.locallySet;
return this.nodeService.updateNode(node.id, permissionBody);
@@ -271,37 +288,37 @@ export class NodePermissionService {
* @param nodeId Id of the node
* @returns node and it's associated roles { node: Node; roles: RoleModel[] }
*/
getNodeWithRoles(nodeId: string): Observable<{ node: Node; roles: RoleModel[] }> {
return this.nodeService.getNode(nodeId).pipe(
getNodeWithRoles(nodeId: string): Observable<{ node: Node; roles: RoleModel[] }> {
return this.nodeService.getNode(nodeId).pipe(
switchMap(node => {
return forkJoin({
node: of(node),
roles: this.getNodeRoles(node)
.pipe(
catchError(() => of(node.permissions?.settable)),
map(_roles => _roles.map(role => ({ role, label: role }))
)
)
});
})
);
}
node: of(node),
roles: this.getNodeRoles(node)
.pipe(
catchError(() => of(node.permissions?.settable)),
map(_roles => _roles.map(role => ({ role, label: role }))
)
)
});
})
);
}
transformNodeToUserPerson(node: Node): { person: EcmUserModel, group: Group } {
let person = null, group = null;
if (node.nodeType === 'cm:person') {
const firstName = node.properties['cm:firstName'];
const lastName = node.properties['cm:lastName'];
const email = node.properties['cm:email'];
const id = node.properties['cm:userName'];
person = new EcmUserModel({ id, firstName, lastName, email});
}
transformNodeToUserPerson(node: Node): { person: EcmUserModel, group: Group } {
let person = null, group = null;
if (node.nodeType === 'cm:person') {
const firstName = node.properties['cm:firstName'];
const lastName = node.properties['cm:lastName'];
const email = node.properties['cm:email'];
const id = node.properties['cm:userName'];
person = new EcmUserModel({ id, firstName, lastName, email });
}
if (node.nodeType === 'cm:authorityContainer') {
const displayName = node.properties['cm:authorityDisplayName'] || node.properties['cm:authorityName'];
const id = node.properties['cm:authorityName'];
group = new Group({ displayName, id });
}
return { person, group };
}
if (node.nodeType === 'cm:authorityContainer') {
const displayName = node.properties['cm:authorityDisplayName'] || node.properties['cm:authorityName'];
const id = node.properties['cm:authorityName'];
group = new Group({ displayName, id });
}
return { person, group };
}
}
@@ -17,10 +17,10 @@
import { Subject } from 'rxjs';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { SearchService, setupTestBed, AlfrescoApiService } from '@alfresco/adf-core';
import { SearchService, setupTestBed } from '@alfresco/adf-core';
import { SearchHeaderQueryBuilderService } from '../../services/search-header-query-builder.service';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { fakeNodePaging } from './../../../mock/document-list.component.mock';
// import { fakeNodePaging } from './../../../mock/document-list.component.mock';
import { SEARCH_QUERY_SERVICE_TOKEN } from '../../search-query-service.token';
import { By } from '@angular/platform-browser';
import { SearchFilterContainerComponent } from './search-filter-container.component';
@@ -47,7 +47,6 @@ describe('SearchFilterContainerComponent', () => {
let fixture: ComponentFixture<SearchFilterContainerComponent>;
let component: SearchFilterContainerComponent;
let queryBuilder: SearchHeaderQueryBuilderService;
let alfrescoApiService: AlfrescoApiService;
const searchMock: any = {
dataLoaded: new Subject()
@@ -68,7 +67,6 @@ describe('SearchFilterContainerComponent', () => {
fixture = TestBed.createComponent(SearchFilterContainerComponent);
component = fixture.componentInstance;
queryBuilder = fixture.componentInstance['searchFilterQueryBuilder'];
alfrescoApiService = TestBed.inject(AlfrescoApiService);
component.col = {key: '123', type: 'text'};
spyOn(queryBuilder, 'getCategoryForColumn').and.returnValue(mockCategory);
fixture.detectChanges();
@@ -113,23 +111,6 @@ describe('SearchFilterContainerComponent', () => {
expect(queryBuilder.getActiveFilters()[0].value).toBe('updated text');
});
it('should emit filterChange after the Apply button is clicked', async (done) => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(Promise.resolve(fakeNodePaging));
spyOn(queryBuilder, 'buildQuery').and.returnValue(null);
component.filterChange.subscribe(() => {
done();
});
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('#filter-menu-button');
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
component.widgetContainer.componentRef.instance.value = 'searchText';
const applyButton = fixture.debugElement.query(By.css('#apply-filter-button'));
applyButton.triggerEventHandler('click', {});
fixture.detectChanges();
await fixture.whenStable();
});
it('should remove active filter after the Clear button is clicked', async () => {
queryBuilder.setActiveFilter('name', 'searchText');
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('#filter-menu-button');
@@ -145,24 +126,6 @@ describe('SearchFilterContainerComponent', () => {
expect(queryBuilder.getActiveFilters().length).toBe(0);
});
it('should emit filterChange after the Clear button is clicked', async (done) => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(Promise.resolve(fakeNodePaging));
spyOn(queryBuilder, 'buildQuery').and.returnValue(null);
component.filterChange.subscribe(() => {
done();
});
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('#filter-menu-button');
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
component.widgetContainer.componentRef.instance.value = 'searchText';
const fakeEvent = jasmine.createSpyObj('event', ['stopPropagation']);
const clearButton = fixture.debugElement.query(By.css('#clear-filter-button'));
clearButton.triggerEventHandler('click', fakeEvent);
fixture.detectChanges();
await fixture.whenStable();
});
it('should emit filterChange after the Enter key is pressed', async (done) => {
spyOn(queryBuilder, 'buildQuery').and.returnValue(null);
component.filterChange.subscribe(() => {
@@ -25,7 +25,8 @@ import {
RequestSortDefinitionInner,
ResultSetPaging,
RequestHighlight,
RequestScope
RequestScope,
SearchApi
} from '@alfresco/js-api';
import { SearchCategory } from '../models/search-category.interface';
import { FilterQuery } from '../models/filter-query.interface';
@@ -284,7 +285,8 @@ export abstract class BaseQueryBuilderService {
try {
const query = queryBody ? queryBody : this.buildQuery();
if (query) {
const resultSetPaging: ResultSetPaging = await this.alfrescoApiService.getInstance().search.searchApi.search(query);
const searchApi = new SearchApi(this.alfrescoApiService.getInstance());
const resultSetPaging: ResultSetPaging = await searchApi.search(query);
this.executed.next(resultSetPaging);
}
} catch (error) {
@@ -302,7 +304,8 @@ export abstract class BaseQueryBuilderService {
}
search(queryBody: QueryBody): Observable<ResultSetPaging> {
const promise = this.alfrescoApiService.searchApi.search(queryBody);
const searchApi = new SearchApi(this.alfrescoApiService.getInstance());
const promise = searchApi.search(queryBody);
promise.then((resultSetPaging) => {
this.executed.next(resultSetPaging);
@@ -410,7 +413,7 @@ export abstract class BaseQueryBuilderService {
}
get hasFacetHighlight(): boolean {
return this.config && this.config.highlight ? true : false;
return !!(this.config && this.config.highlight);
}
protected get sort(): RequestSortDefinitionInner[] {
@@ -16,17 +16,20 @@
*/
import { SearchConfiguration } from '../models/search-configuration.interface';
import { AppConfigService } from '@alfresco/adf-core';
import { AppConfigService, CoreModule, setupTestBed } from '@alfresco/adf-core';
import { SearchHeaderQueryBuilderService } from './search-header-query-builder.service';
import { TestBed } from '@angular/core/testing';
import { ContentTestingModule } from '../../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
describe('SearchHeaderQueryBuilderService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ContentTestingModule]
});
setupTestBed({
imports: [
TranslateModule.forRoot(),
CoreModule.forRoot(),
ContentTestingModule
]
});
const buildConfig = (searchSettings): AppConfigService => {
@@ -17,7 +17,7 @@
import { AlfrescoApiService, LogService } from '@alfresco/adf-core';
import { Injectable } from '@angular/core';
import { RatingEntry, RatingBody } from '@alfresco/js-api';
import { RatingEntry, RatingBody, RatingsApi } from '@alfresco/js-api';
import { from, throwError, Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
@@ -26,7 +26,10 @@ import { catchError } from 'rxjs/operators';
})
export class RatingService {
ratingsApi: RatingsApi;
constructor(private apiService: AlfrescoApiService, private logService: LogService) {
this.ratingsApi = new RatingsApi(this.apiService.getInstance());
}
/**
@@ -36,7 +39,7 @@ export class RatingService {
* @returns The rating value
*/
getRating(nodeId: string, ratingType: any): Observable<RatingEntry | {}> {
return from(this.apiService.getInstance().core.ratingsApi.getRating(nodeId, ratingType))
return from(this.ratingsApi.getRating(nodeId, ratingType))
.pipe(
catchError(this.handleError)
);
@@ -54,7 +57,7 @@ export class RatingService {
'id': ratingType,
'myRating': vote
});
return from(this.apiService.getInstance().core.ratingsApi.rate(nodeId, ratingBody))
return from(this.ratingsApi.createRating(nodeId, ratingBody))
.pipe(
catchError(this.handleError)
);
@@ -67,7 +70,7 @@ export class RatingService {
* @returns Null response indicating that the operation is complete
*/
deleteRating(nodeId: string, ratingType: any): Observable<any> {
return from(this.apiService.getInstance().core.ratingsApi.removeRating(nodeId, ratingType))
return from(this.ratingsApi.deleteRating(nodeId, ratingType))
.pipe(
catchError(this.handleError)
);
@@ -19,7 +19,7 @@ import { AlfrescoApiService, LogService } from '@alfresco/adf-core';
import { EventEmitter, Injectable, Output } from '@angular/core';
import { Observable, from, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { TagBody, TagPaging, TagEntry } from '@alfresco/js-api';
import { TagBody, TagPaging, TagEntry, TagsApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
@@ -27,12 +27,15 @@ import { TagBody, TagPaging, TagEntry } from '@alfresco/js-api';
// tslint:disable-next-line: directive-class-suffix
export class TagService {
private tagsApi: TagsApi;
/** Emitted when tag information is updated. */
@Output()
refresh = new EventEmitter();
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.tagsApi = new TagsApi(this.apiService.getInstance());
}
/**
@@ -41,7 +44,7 @@ export class TagService {
* @returns TagPaging object (defined in JS-API) containing the tags
*/
getTagsByNodeId(nodeId: string): Observable<TagPaging> {
return from(this.apiService.getInstance().core.tagsApi.getNodeTags(nodeId)).pipe(
return from(this.tagsApi.listTagsForNode(nodeId)).pipe(
catchError((err) => this.handleError(err))
);
}
@@ -52,7 +55,7 @@ export class TagService {
* @returns TagPaging object (defined in JS-API) containing the tags
*/
getAllTheTags(opts?: any): Observable<TagPaging> {
return from(this.apiService.getInstance().core.tagsApi.getTags(opts))
return from(this.tagsApi.listTags(opts))
.pipe(catchError((err) => this.handleError(err)));
}
@@ -66,7 +69,7 @@ export class TagService {
const tagBody = new TagBody();
tagBody.tag = tagName;
const observableAdd = from(this.apiService.getInstance().core.tagsApi.addTag(nodeId, [tagBody]));
const observableAdd = from(this.tagsApi.createTagForNode(nodeId, [tagBody]));
observableAdd.subscribe((tagEntry: TagEntry) => {
this.refresh.emit(tagEntry);
@@ -84,7 +87,7 @@ export class TagService {
* @returns Null object when the operation completes
*/
removeTag(nodeId: string, tag: string): Observable<any> {
const observableRemove = from(this.apiService.getInstance().core.tagsApi.removeTag(nodeId, tag));
const observableRemove = from(this.tagsApi.deleteTagFromNode(nodeId, tag));
observableRemove.subscribe((data) => {
this.refresh.emit(data);
@@ -23,7 +23,7 @@ import { UploadButtonComponent } from './upload-button.component';
import { NodeEntry } from '@alfresco/js-api';
import { ContentTestingModule } from '../../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { mockUploadErrorPromise, mockUploadSuccessPromise } from '../../mock/upload.service.mock';
import { mockUploadErrorPromise } from '../../mock/upload.service.mock';
describe('UploadButtonComponent', () => {
@@ -420,17 +420,6 @@ describe('UploadButtonComponent', () => {
fixture.detectChanges();
});
it('should emit an success for successful upload of a file', (done) => {
spyOn(uploadService, 'getUploadPromise').and.returnValue(mockUploadSuccessPromise);
component.success.subscribe((success) => {
expect(success).not.toBeNull();
done();
});
component.onFilesAdded(fakeEvent);
});
it('should emit error if upload errored', (done) => {
spyOn(uploadService, 'getUploadPromise').and.returnValue(mockUploadErrorPromise);
@@ -19,17 +19,16 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { VersionListComponent } from './version-list.component';
import { AlfrescoApiService, setupTestBed } from '@alfresco/adf-core';
import { setupTestBed } from '@alfresco/adf-core';
import { MatDialog } from '@angular/material/dialog';
import { of } from 'rxjs';
import { Node, VersionPaging, VersionEntry } from '@alfresco/js-api';
import { Node, VersionPaging, VersionEntry, NodeEntry } from '@alfresco/js-api';
import { ContentTestingModule } from '../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
describe('VersionListComponent', () => {
let component: VersionListComponent;
let fixture: ComponentFixture<VersionListComponent>;
let alfrescoApiService: AlfrescoApiService;
let dialog: MatDialog;
const nodeId = 'test-id';
@@ -59,14 +58,13 @@ describe('VersionListComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(VersionListComponent);
alfrescoApiService = TestBed.inject(AlfrescoApiService);
dialog = TestBed.inject(MatDialog);
component = fixture.componentInstance;
component.node = <Node> { id: nodeId, allowableOperations: ['update'] };
spyOn(component, 'downloadContent').and.stub();
spyOn(alfrescoApiService.nodesApi, 'getNodeInfo').and.returnValue(Promise.resolve(<Node> { id: 'nodeInfoId' }));
spyOn(component['nodesApi'], 'getNode').and.returnValue(Promise.resolve(<NodeEntry> { entry: { id: 'nodeInfoId' } }));
});
it('should raise confirmation dialog on delete', () => {
@@ -93,12 +91,12 @@ describe('VersionListComponent', () => {
}
} as any);
spyOn(alfrescoApiService.versionsApi, 'deleteVersion').and.returnValue(Promise.resolve(true));
spyOn(component['versionsApi'], 'deleteVersion').and.returnValue(Promise.resolve(true));
component.deleteVersion(versionId);
expect(dialog.open).toHaveBeenCalled();
expect(alfrescoApiService.versionsApi.deleteVersion).toHaveBeenCalledWith(nodeId, versionId);
expect(component['versionsApi'].deleteVersion).toHaveBeenCalledWith(nodeId, versionId);
});
it('should not delete version if user rejects', () => {
@@ -110,12 +108,12 @@ describe('VersionListComponent', () => {
}
} as any);
spyOn(alfrescoApiService.versionsApi, 'deleteVersion').and.returnValue(Promise.resolve(true));
spyOn(component['versionsApi'], 'deleteVersion').and.returnValue(Promise.resolve(true));
component.deleteVersion(versionId);
expect(dialog.open).toHaveBeenCalled();
expect(alfrescoApiService.versionsApi.deleteVersion).not.toHaveBeenCalled();
expect(component['versionsApi'].deleteVersion).not.toHaveBeenCalled();
});
it('should reload and raise deleted event', (done) => {
@@ -131,7 +129,7 @@ describe('VersionListComponent', () => {
describe('Version history fetching', () => {
it('should use loading bar', () => {
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and
spyOn(component['versionsApi'], 'listVersionHistory').and
.callFake(() => Promise.resolve({ list: { entries: versionTest } }));
let loadingProgressBar = fixture.debugElement.query(By.css('[data-automation-id="version-history-loading-bar"]'));
@@ -145,18 +143,18 @@ describe('VersionListComponent', () => {
});
it('should load the versions for a given id', () => {
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and
spyOn(component['versionsApi'], 'listVersionHistory').and
.callFake(() => Promise.resolve({ list: { entries: versionTest } }));
component.ngOnChanges();
fixture.detectChanges();
expect(alfrescoApiService.versionsApi.listVersionHistory).toHaveBeenCalledWith(nodeId);
expect(component['versionsApi'].listVersionHistory).toHaveBeenCalledWith(nodeId);
});
it('should show the versions after loading', (done) => {
fixture.detectChanges();
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and.callFake(() => {
spyOn(component['versionsApi'], 'listVersionHistory').and.callFake(() => {
return Promise.resolve(new VersionPaging({
list: {
entries: [
@@ -184,7 +182,7 @@ describe('VersionListComponent', () => {
});
it('should NOT show the versions comments if input property is set not to show them', (done) => {
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and
spyOn(component['versionsApi'], 'listVersionHistory').and
.callFake(() => Promise.resolve(
new VersionPaging({
list: {
@@ -219,13 +217,13 @@ describe('VersionListComponent', () => {
versionComment: 'test-version-comment'
}
};
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and.returnValue(Promise.resolve(new VersionPaging({ list: { entries: [versionEntry] } })));
spyOn(alfrescoApiService.contentApi, 'getContentUrl').and.returnValue('the/download/url');
spyOn(component['versionsApi'], 'listVersionHistory').and.returnValue(Promise.resolve(new VersionPaging({ list: { entries: [versionEntry] } })));
spyOn(component['contentApi'], 'getContentUrl').and.returnValue('the/download/url');
fixture.detectChanges();
component.downloadVersion('1.0');
expect(alfrescoApiService.contentApi.getContentUrl).toHaveBeenCalledWith(nodeId, true);
expect(component['contentApi'].getContentUrl).toHaveBeenCalledWith(nodeId, true);
});
it('should be able to view a version', () => {
@@ -243,9 +241,9 @@ describe('VersionListComponent', () => {
versionComment: 'test-version-comment'
}
};
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and
spyOn(component['versionsApi'], 'listVersionHistory').and
.callFake(() => Promise.resolve(new VersionPaging({ list: { entries: [versionEntry] } })));
const spyOnDownload = spyOn(alfrescoApiService.contentApi, 'getContentUrl').and.stub();
const spyOnDownload = spyOn(component['contentApi'], 'getContentUrl').and.stub();
component.allowDownload = false;
fixture.detectChanges();
@@ -253,32 +251,22 @@ describe('VersionListComponent', () => {
component.downloadVersion('1.0');
expect(spyOnDownload).not.toHaveBeenCalled();
});
});
});
describe('Version restoring', () => {
it('should reload and raise version-restored DOM event', (done) => {
spyOn(component, 'loadVersionHistory').and.stub();
component.restored.subscribe(() => {
expect(component.loadVersionHistory).toHaveBeenCalled();
done();
});
fixture.detectChanges();
component.onVersionRestored({});
});
it('should restore version only when restore allowed', () => {
component.node.allowableOperations = [];
spyOn(alfrescoApiService.versionsApi, 'revertVersion').and.stub();
spyOn(component['versionsApi'], 'revertVersion').and.stub();
component.restore('1');
expect(alfrescoApiService.versionsApi.revertVersion).not.toHaveBeenCalled();
expect(component['versionsApi'].revertVersion).not.toHaveBeenCalled();
});
it('should load the versions for a given id', () => {
fixture.detectChanges();
component.versions = versionTest;
const spyOnRevertVersion = spyOn(alfrescoApiService.versionsApi, 'revertVersion').and
const spyOnRevertVersion = spyOn(component['versionsApi'], 'revertVersion').and
.callFake(() => Promise.resolve(new VersionEntry(
{ entry: { name: 'test-file-name', id: '1.0', versionComment: 'test-version-comment' } })));
@@ -290,29 +278,29 @@ describe('VersionListComponent', () => {
it('should get node info after restoring the node', fakeAsync(() => {
fixture.detectChanges();
component.versions = versionTest;
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory')
spyOn(component['versionsApi'], 'listVersionHistory')
.and.callFake(() => Promise.resolve({ list: { entries: versionTest } }));
spyOn(alfrescoApiService.versionsApi, 'revertVersion')
spyOn(component['versionsApi'], 'revertVersion')
.and.callFake(() => Promise.resolve(new VersionEntry(
{ entry: { name: 'test-file-name', id: '1.0', versionComment: 'test-version-comment' } })));
{ entry: { name: 'test-file-name', id: '1.0', versionComment: 'test-version-comment' } })));
component.restore(versionId);
fixture.detectChanges();
tick();
expect(alfrescoApiService.nodesApi.getNodeInfo).toHaveBeenCalled();
expect(component['nodesApi'].getNode).toHaveBeenCalled();
}));
it('should emit with node info data', fakeAsync(() => {
fixture.detectChanges();
component.versions = versionTest;
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory')
spyOn(component['versionsApi'], 'listVersionHistory')
.and.callFake(() => Promise.resolve({ list: { entries: versionTest } }));
spyOn(alfrescoApiService.versionsApi, 'revertVersion')
spyOn(component['versionsApi'], 'revertVersion')
.and.callFake(() => Promise.resolve(new VersionEntry(
{ entry: { name: 'test-file-name', id: '1.0', versionComment: 'test-version-comment' } })));
{ entry: { name: 'test-file-name', id: '1.0', versionComment: 'test-version-comment' } })));
spyOn(component.restored, 'emit');
@@ -327,9 +315,9 @@ describe('VersionListComponent', () => {
fixture.detectChanges();
component.versions = versionTest;
const spyOnListVersionHistory = spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and
const spyOnListVersionHistory = spyOn(component['versionsApi'], 'listVersionHistory').and
.callFake(() => Promise.resolve({ list: { entries: versionTest } }));
spyOn(alfrescoApiService.versionsApi, 'revertVersion').and.callFake(() => Promise.resolve(null));
spyOn(component['versionsApi'], 'revertVersion').and.callFake(() => Promise.resolve(null));
component.restore(versionId);
fixture.detectChanges();
@@ -346,7 +334,7 @@ describe('VersionListComponent', () => {
beforeEach(() => {
fixture.detectChanges();
component.node = new Node({ id: nodeId });
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and.callFake(() => {
spyOn(component['versionsApi'], 'listVersionHistory').and.callFake(() => {
return Promise.resolve(new VersionPaging({
list: {
entries: [
@@ -395,7 +383,7 @@ describe('VersionListComponent', () => {
beforeEach(() => {
fixture.detectChanges();
component.node = <Node> { id: nodeId };
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and.callFake(() => {
spyOn(component['versionsApi'], 'listVersionHistory').and.callFake(() => {
return Promise.resolve(new VersionPaging({
list: {
entries: [
@@ -445,7 +433,7 @@ describe('VersionListComponent', () => {
beforeEach(() => {
fixture.detectChanges();
component.node = <Node> { id: nodeId, allowableOperations: ['update', 'delete'] };
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and.callFake(() => {
spyOn(component['versionsApi'], 'listVersionHistory').and.callFake(() => {
return Promise.resolve(new VersionPaging({
list: {
entries: [
@@ -17,7 +17,7 @@
import { AlfrescoApiService, ContentService } from '@alfresco/adf-core';
import { Component, Input, OnChanges, ViewEncapsulation, EventEmitter, Output } from '@angular/core';
import { VersionsApi, Node, VersionEntry, VersionPaging } from '@alfresco/js-api';
import { VersionsApi, Node, VersionEntry, VersionPaging, NodesApi, NodeEntry, ContentApi } from '@alfresco/js-api';
import { MatDialog } from '@angular/material/dialog';
import { ConfirmDialogComponent } from '../dialogs/confirm.dialog';
@@ -33,6 +33,8 @@ import { ConfirmDialogComponent } from '../dialogs/confirm.dialog';
export class VersionListComponent implements OnChanges {
private versionsApi: VersionsApi;
private nodesApi: NodesApi;
private contentApi: ContentApi;
versions: VersionEntry[] = [];
isLoading = true;
@@ -71,7 +73,9 @@ export class VersionListComponent implements OnChanges {
constructor(private alfrescoApi: AlfrescoApiService,
private contentService: ContentService,
private dialog: MatDialog) {
this.versionsApi = this.alfrescoApi.versionsApi;
this.versionsApi = new VersionsApi(this.alfrescoApi.getInstance());
this.nodesApi = new NodesApi(this.alfrescoApi.getInstance());
this.contentApi = new ContentApi(this.alfrescoApi.getInstance());
}
ngOnChanges() {
@@ -91,7 +95,7 @@ export class VersionListComponent implements OnChanges {
this.versionsApi
.revertVersion(this.node.id, versionId, { majorVersion: true, comment: '' })
.then(() =>
this.alfrescoApi.nodesApi.getNodeInfo(
this.nodesApi.getNode(
this.node.id,
{ include: ['permissions', 'path', 'isFavorite', 'allowableOperations'] }
)
@@ -133,7 +137,7 @@ export class VersionListComponent implements OnChanges {
dialogRef.afterClosed().subscribe((result) => {
if (result === true) {
this.alfrescoApi.versionsApi
this.versionsApi
.deleteVersion(this.node.id, versionId)
.then(() => this.onVersionDeleted(this.node));
}
@@ -146,13 +150,13 @@ export class VersionListComponent implements OnChanges {
this.deleted.emit(node);
}
onVersionRestored(node: any) {
onVersionRestored(node: NodeEntry) {
this.loadVersionHistory();
this.restored.emit(node);
this.restored.emit(node?.entry);
}
private getVersionContentUrl(nodeId: string, versionId: string, attachment?: boolean) {
const nodeDownloadUrl = this.alfrescoApi.contentApi.getContentUrl(nodeId, attachment);
const nodeDownloadUrl = this.contentApi.getContentUrl(nodeId, attachment);
return nodeDownloadUrl.replace('/content', '/versions/' + versionId + '/content');
}
@@ -58,7 +58,7 @@ describe('VersionManagerComponent', () => {
component.node = node;
alfrescoApiService = TestBed.inject(AlfrescoApiService);
spyOnListVersionHistory = spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and
spyOnListVersionHistory = spyOn(component.versionListComponent['versionsApi'], 'listVersionHistory').and
.callFake(() => Promise.resolve(new VersionPaging({ list: { entries: [ versionEntry ] }})));
});
@@ -17,6 +17,7 @@
import { ObjectDataTableAdapter, AlfrescoApiService, LogService } from '@alfresco/adf-core';
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
import { WebscriptApi } from '@alfresco/js-api';
/**
* <adf-webscript-get [scriptPath]="string"
@@ -80,8 +81,11 @@ export class WebscriptComponent implements OnChanges {
data: any = undefined;
showError: boolean = false;
webscriptApi: WebscriptApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.webscriptApi = new WebscriptApi(this.apiService.getInstance());
}
ngOnChanges() {
@@ -90,7 +94,7 @@ export class WebscriptComponent implements OnChanges {
}
return new Promise<void>((resolve, reject) => {
this.apiService.getInstance().webScript.executeWebScript('GET', this.scriptPath, this.scriptArgs, this.contextRoot, this.servicePath).then((webScriptData) => {
this.webscriptApi.executeWebScript('GET', this.scriptPath, this.scriptArgs, this.contextRoot, this.servicePath).then((webScriptData) => {
this.data = webScriptData;
@@ -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);
});
@@ -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();
});
});
@@ -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);
@@ -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(() => {
@@ -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));
}
}
@@ -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();
});
});
+8 -3
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(
@@ -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');
});
@@ -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;
}
@@ -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' } }
@@ -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(() => ({
@@ -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();
});
});
@@ -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(() => ({
@@ -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', () => {
@@ -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> {
@@ -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> {};
});
@@ -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());
@@ -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>' });
});
@@ -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';
@@ -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))
+10 -6
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))
@@ -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) => {
+43 -42
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) => {
@@ -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)));
}
@@ -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);
+3 -9
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)
};
+5 -69
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);
}
}
+7 -4
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))
@@ -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);
+8 -3
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 {
+6 -3
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();
}
/**
+6 -3
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[] = [];
@@ -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));
});
+8 -4
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({
+14 -33
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 {
@@ -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))
@@ -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>');
});
});
});
+10 -8
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)) {
+7 -23
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) {
+16 -17
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(
+1 -4
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)) {
-164
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();
});
});
});
+15 -13
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() {
@@ -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');
});
});
@@ -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);
+3 -5
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());
}
/**
+14 -8
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);
}
/**
+12 -7
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 }));
}
/**
+7 -10
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) => {
+10 -5
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);
@@ -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))
+2 -2
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());
}
/**
+1 -4
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');
});
});
+6 -3
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;
+3 -6
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 }, {
+28 -40
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));
}
-1
View File
@@ -44,6 +44,5 @@ export const setupTestBed = (moduleDef: TestModuleMetadata) => {
.catch(done.fail);
}
);
afterAll(() => allowAngularToReset());
};
@@ -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);
}));
});
});
@@ -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', () => {
+67 -42
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);
+27 -20
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;
@@ -28,19 +28,25 @@ import { MultiBarChart } from '../../diagram/models/chart/multi-bar-chart.model'
import { PieChart } from '../../diagram/models/chart/pie-chart.model';
import { TableChart } from '../../diagram/models/chart/table-chart.model';
import { map, catchError } from 'rxjs/operators';
import { ProcessDefinitionsApi, ReportApi } from '@alfresco/js-api';
@Injectable({ providedIn: 'root' })
export class AnalyticsService {
reportApi: ReportApi;
processDefinitionsApi: ProcessDefinitionsApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.reportApi = new ReportApi(this.apiService.getInstance());
this.processDefinitionsApi = new ProcessDefinitionsApi(this.apiService.getInstance());
}
/**
* Retrieve all the Deployed app
*/
getReportList(appId: number): Observable<ReportParametersModel[]> {
return from(this.apiService.getInstance().activiti.reportApi.getReportList())
return from(this.reportApi.getReportList())
.pipe(
map((res: any) => {
const reports: ReportParametersModel[] = [];
@@ -61,7 +67,7 @@ export class AnalyticsService {
* @param reportName - string - The name of report
*/
getReportByName(reportName: string): Observable<any> {
return from(this.apiService.getInstance().activiti.reportApi.getReportList())
return from(this.reportApi.getReportList())
.pipe(
map((response: any) => {
return response.find((report) => report.name === reportName);
@@ -79,7 +85,7 @@ export class AnalyticsService {
}
getReportParams(reportId: string): Observable<ReportParametersModel> {
return from(this.apiService.getInstance().activiti.reportApi.getReportParams(reportId))
return from(this.reportApi.getReportParams(reportId))
.pipe(
map((res: any) => {
return new ReportParametersModel(res);
@@ -139,7 +145,7 @@ export class AnalyticsService {
}
getProcessDefinitionsValuesNoApp(): Observable<ParameterValueModel[]> {
return from(this.apiService.getInstance().activiti.reportApi.getProcessDefinitions())
return from(this.reportApi.getProcessDefinitions())
.pipe(
map((res: any) => {
const paramOptions: ParameterValueModel[] = [];
@@ -154,7 +160,7 @@ export class AnalyticsService {
getProcessDefinitionsValues(appId: number): Observable<ParameterValueModel[]> {
const options = { 'appDefinitionId': appId };
return from(this.apiService.getInstance().activiti.processDefinitionsApi.getProcessDefinitions(options))
return from(this.processDefinitionsApi.getProcessDefinitions(options))
.pipe(
map((res: any) => {
const paramOptions: ParameterValueModel[] = [];
@@ -168,7 +174,7 @@ export class AnalyticsService {
}
getTasksByProcessDefinitionId(reportId: string, processDefinitionId: string): Observable<ParameterValueModel[]> {
return from(this.apiService.getInstance().activiti.reportApi.getTasksByProcessDefinitionId(reportId, processDefinitionId))
return from(this.reportApi.getTasksByProcessDefinitionId(reportId, processDefinitionId))
.pipe(
map((res: any) => {
const paramOptions: ParameterValueModel[] = [];
@@ -182,7 +188,7 @@ export class AnalyticsService {
}
getReportsByParams(reportId: string, paramsQuery: any): Observable<Chart[]> {
return from(this.apiService.getInstance().activiti.reportApi.getReportsByParams(reportId, paramsQuery))
return from(this.reportApi.getReportsByParams(reportId, paramsQuery))
.pipe(
map((res: any) => {
const elements: Chart[] = [];
@@ -209,7 +215,7 @@ export class AnalyticsService {
}
createDefaultReports(): Observable<any> {
return from(this.apiService.getInstance().activiti.reportApi.createDefaultReports())
return from(this.reportApi.createDefaultReports())
.pipe(
map(res => res || {}),
catchError((err) => this.handleError(err))
@@ -217,7 +223,7 @@ export class AnalyticsService {
}
updateReport(reportId: string, name: string): Observable<any> {
return from(this.apiService.getInstance().activiti.reportApi.updateReport(reportId, name))
return from(this.reportApi.updateReport(reportId, name))
.pipe(
map(() => this.logService.info('upload')),
catchError((err) => this.handleError(err))
@@ -225,7 +231,7 @@ export class AnalyticsService {
}
exportReportToCsv(reportId: string, paramsQuery: any): Observable<any> {
return from(this.apiService.getInstance().activiti.reportApi.exportToCsv(reportId, paramsQuery))
return from(this.reportApi.exportToCsv(reportId, paramsQuery))
.pipe(
map((res: any) => {
this.logService.info('export');
@@ -236,7 +242,7 @@ export class AnalyticsService {
}
saveReport(reportId: string, paramsQuery: any): Observable<any> {
return from(this.apiService.getInstance().activiti.reportApi.saveReport(reportId, paramsQuery))
return from(this.reportApi.saveReport(reportId, paramsQuery))
.pipe(
map(() => {
this.logService.info('save');
@@ -246,7 +252,7 @@ export class AnalyticsService {
}
deleteReport(reportId: string): Observable<any> {
return from(this.apiService.getInstance().activiti.reportApi.deleteReport(reportId))
return from(this.reportApi.deleteReport(reportId))
.pipe(
map(() => {
this.logService.info('delete');
@@ -19,23 +19,27 @@ import { AlfrescoApiService, LogService } from '@alfresco/adf-core';
import { Injectable } from '@angular/core';
import { Observable, from, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { ModelJsonBpmnApi } from '@alfresco/js-api';
@Injectable({ providedIn: 'root' })
export class DiagramsService {
private modelJsonBpmnApi: ModelJsonBpmnApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.modelJsonBpmnApi = new ModelJsonBpmnApi(this.apiService.getInstance());
}
getProcessDefinitionModel(processDefinitionId: string): Observable<any> {
return from(this.apiService.getInstance().activiti.modelJsonBpmnApi.getModelJSON(processDefinitionId))
return from(this.modelJsonBpmnApi.getModelJSON(processDefinitionId))
.pipe(
catchError((err) => this.handleError(err))
);
}
getRunningProcessDefinitionModel(processInstanceId: string): Observable<any> {
return from(this.apiService.getInstance().activiti.modelJsonBpmnApi.getModelJSONForProcessDefinition(processInstanceId))
return from(this.modelJsonBpmnApi.getModelJSONForProcessDefinition(processInstanceId))
.pipe(
catchError((err) => this.handleError(err))
);
@@ -29,7 +29,6 @@ import {
FormService,
DownloadService,
AppConfigService,
AlfrescoApiService,
UploadWidgetContentLinkModel
} from '@alfresco/adf-core';
import {
@@ -79,7 +78,6 @@ describe('AttachFileCloudWidgetComponent', () => {
let processCloudContentService: ProcessCloudContentService;
let formService: FormService;
let downloadService: DownloadService;
let alfrescoApiService: AlfrescoApiService;
let contentNodeSelectorPanelService: ContentNodeSelectorPanelService;
let apiServiceSpy: jasmine.Spy;
let contentModelFormFileHandlerSpy: jasmine.Spy;
@@ -127,7 +125,6 @@ describe('AttachFileCloudWidgetComponent', () => {
AppConfigService
);
formService = TestBed.inject(FormService);
alfrescoApiService = TestBed.inject(AlfrescoApiService);
contentNodeSelectorPanelService = TestBed.inject(ContentNodeSelectorPanelService);
openUploadFileDialogSpy = spyOn(contentCloudNodeSelectorService, 'openUploadFileDialog').and.returnValue(of([fakeMinimalNode]));
});
@@ -533,7 +530,7 @@ describe('AttachFileCloudWidgetComponent', () => {
describe('when a file is uploaded', () => {
beforeEach(async () => {
apiServiceSpy = spyOn(alfrescoApiService.getInstance().node, 'getNode').and.returnValue(new Promise(resolve => resolve({entry: fakeNodeWithProperties})));
apiServiceSpy = spyOn(widget['nodesApi'], 'getNode').and.returnValue(new Promise(resolve => resolve({entry: fakeNodeWithProperties})));
spyOn(contentCloudNodeSelectorService, 'fetchNodeIdFromRelativePath').and.returnValue(new Promise(resolve => resolve('fake-properties')));
openUploadFileDialogSpy.and.returnValue(of([fakeNodeWithProperties]));
widget.field = new FormFieldModel(new FormModel(), {
@@ -700,7 +697,7 @@ describe('AttachFileCloudWidgetComponent', () => {
describe('contentModelFormFileHandler', () => {
beforeEach(async () => {
apiServiceSpy = spyOn(alfrescoApiService.getInstance().node, 'getNode').and.returnValue(new Promise(resolve => resolve({ entry: fakeNodeWithProperties })));
apiServiceSpy = spyOn(widget['nodesApi'], 'getNode').and.returnValue(new Promise(resolve => resolve({ entry: fakeNodeWithProperties })));
contentModelFormFileHandlerSpy = spyOn(widget, 'contentModelFormFileHandler').and.callThrough();
updateFormSpy = spyOn(formService.updateFormValuesRequested, 'next');
contentClickedSpy = spyOn(formService.formContentClicked, 'next');
@@ -29,7 +29,7 @@ import {
AlfrescoApiService,
UploadWidgetContentLinkModel
} from '@alfresco/adf-core';
import { Node, RelatedContentRepresentation } from '@alfresco/js-api';
import { Node, NodesApi, RelatedContentRepresentation } from '@alfresco/js-api';
import { ContentCloudNodeSelectorService } from '../../../services/content-cloud-node-selector.service';
import { ProcessCloudContentService } from '../../../services/process-cloud-content.service';
import { UploadCloudWidgetComponent } from './upload-cloud.widget';
@@ -67,6 +67,8 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
rootNodeId = AttachFileCloudWidgetComponent.ALIAS_USER_FOLDER;
selectedNode: Node;
private nodesApi: NodesApi;
constructor(
formService: FormService,
logger: LogService,
@@ -79,6 +81,7 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
private contentNodeSelectorPanelService: ContentNodeSelectorPanelService
) {
super(formService, thumbnails, processCloudContentService, notificationService, logger);
this.nodesApi = new NodesApi(this.apiService.getInstance());
}
ngOnInit() {
@@ -222,7 +225,7 @@ export class AttachFileCloudWidgetComponent extends UploadCloudWidgetComponent i
contentModelFormFileHandler(file?: any) {
if (file?.id && this.isRetrieveMetadataOptionEnabled()) {
const values: FormValues = {};
this.apiService.getInstance().node.getNode(file.id).then(acsNode => {
this.nodesApi.getNode(file.id).then(acsNode => {
const metadata = acsNode?.entry?.properties;
if (metadata) {
const keys = Object.keys(metadata);
@@ -1,143 +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 { AlfrescoApiService, NotificationService, setupTestBed } from '@alfresco/adf-core';
import { ProcessServiceCloudTestingModule } from '../../testing/process-service-cloud.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { ContentCloudNodeSelectorService } from 'process-services-cloud';
import { MatDialog } from '@angular/material/dialog';
import { of, Subject } from 'rxjs';
import { ContentNodeSelectorComponent, ContentNodeSelectorComponentData } from '@alfresco/adf-content-services';
describe('ContentCloudNodeSelectorService', () => {
let service: ContentCloudNodeSelectorService;
let apiService: AlfrescoApiService;
let notificationService: NotificationService;
let getNodeSpy: jasmine.Spy;
let dialog: MatDialog;
let openDialogSpy: jasmine.Spy;
let showWarningSpy: jasmine.Spy;
const relativePathNodeResponseBody = {
entry: {
id: 'mock-relative-path-node-id'
}
};
const aliasNodeResponseBody = {
entry: {
id: 'mock-alias-node-id'
}
};
setupTestBed({
imports: [TranslateModule.forRoot(), ProcessServiceCloudTestingModule]
});
beforeEach(() => {
service = TestBed.inject(ContentCloudNodeSelectorService);
notificationService = TestBed.inject(NotificationService);
apiService = TestBed.inject(AlfrescoApiService);
dialog = TestBed.inject(MatDialog);
showWarningSpy = spyOn(notificationService, 'showWarning');
openDialogSpy = spyOn(dialog, 'open').and.callFake(() => ({
afterOpened: () => of({}),
afterClosed: () => of({}),
componentInstance: {
body: '',
error: new Subject<any>()
}
}));
getNodeSpy = spyOn(apiService.nodesApi, 'getNode');
});
it('should be able to open the content node select panel dialog', () => {
const mockData = <ContentNodeSelectorComponentData> {
title: 'Select a file',
actionName: 'ATTACH',
currentFolderId: 'nodeId',
selectionMode: 'single'
};
service.openUploadFileDialog('nodeId', 'single', true, true);
const args = openDialogSpy.calls.allArgs()[0];
expect(openDialogSpy).toHaveBeenCalled();
expect(args[0]).toEqual(ContentNodeSelectorComponent);
expect(args[1].data.title).toEqual(mockData.title);
expect(args[1].data.actionName).toEqual(mockData.actionName);
expect(args[1].panelClass).toEqual('adf-content-node-selector-dialog');
expect(args[1].data.selectionMode).toEqual(mockData.selectionMode);
expect(args[1].data.currentFolderId).toEqual('nodeId');
});
it('should be able to set sourceNodeNotFound value to true if the relative path is invalid/deleted', async () => {
expect(service.sourceNodeNotFound).toBe(false);
getNodeSpy.and.returnValue(Promise.reject('Not exists'));
await service.fetchNodeIdFromRelativePath('mock-alias', { relativePath: 'mock-wrong-relativePath' });
expect(getNodeSpy).toHaveBeenCalledWith('mock-alias', {
relativePath: 'mock-wrong-relativePath'
});
expect(service.sourceNodeNotFound).toBe(true);
});
it('should be able to set sourceNodeNotFound value to false after the dialog close', async () => {
service.sourceNodeNotFound = true;
service.openUploadFileDialog('nodeId', 'single', true, true);
service.close();
expect(service.sourceNodeNotFound).toBe(false);
});
it('should be able to show a notification if the relative path is invalid/deleted', () => {
service.sourceNodeNotFound = true;
service.openUploadFileDialog('nodeId', 'single', true, true);
expect(showWarningSpy).toHaveBeenCalledWith('ADF_CLOUD_TASK_FORM.ERROR.DESTINATION_FOLDER_PATH_ERROR');
});
it('should not show a notification if the relative path is valid', () => {
service.sourceNodeNotFound = false;
service.openUploadFileDialog('nodeId', 'single', true, true);
expect(showWarningSpy).not.toHaveBeenCalled();
});
it('should be able to fetch given relative path node id', async () => {
getNodeSpy.and.returnValue(Promise.resolve(relativePathNodeResponseBody));
await service.fetchNodeIdFromRelativePath('mock-alias', { relativePath: 'mock-relativePath' });
expect(getNodeSpy).toHaveBeenCalledWith('mock-alias', {
relativePath: 'mock-relativePath'
});
expect(service.sourceNodeNotFound).toBe(false);
});
it('should be able to fetch given alias node id', async () => {
getNodeSpy.and.returnValue(Promise.resolve(aliasNodeResponseBody));
await service.fetchAliasNodeId('mock-alias');
expect(getNodeSpy).toHaveBeenCalledWith('mock-alias');
});
});
@@ -18,21 +18,27 @@
import { Injectable } from '@angular/core';
import { AlfrescoApiService, NotificationService } from '@alfresco/adf-core';
import { MatDialog } from '@angular/material/dialog';
import { ContentNodeSelectorComponent, ContentNodeSelectorComponentData, NodeAction } from '@alfresco/adf-content-services';
import { Node } from '@alfresco/js-api';
import {
ContentNodeSelectorComponent,
ContentNodeSelectorComponentData,
NodeAction
} from '@alfresco/adf-content-services';
import { Node, NodesApi } from '@alfresco/js-api';
import { Observable, Subject, throwError } from 'rxjs';
@Injectable({
providedIn: 'root'
providedIn: 'root'
})
export class ContentCloudNodeSelectorService {
nodesApi: NodesApi;
sourceNodeNotFound = false;
constructor(
private apiService: AlfrescoApiService,
private notificationService: NotificationService,
private dialog: MatDialog) {
this.nodesApi = new NodesApi(this.apiService.getInstance());
}
openUploadFileDialog(currentFolderId?: string, selectionMode?: string, isAllFileSources?: boolean, restrictRootToCurrentFolderId?: boolean): Observable<Node[]> {
@@ -55,7 +61,7 @@ export class ContentCloudNodeSelectorService {
}
async fetchNodeIdFromRelativePath(alias: string, opts: { relativePath: string }): Promise<string> {
const relativePathNodeEntry: any = await this.apiService.nodesApi
const relativePathNodeEntry: any = await this.nodesApi
.getNode(alias, opts)
.catch((err) => {
this.sourceNodeNotFound = true;
@@ -65,9 +71,9 @@ export class ContentCloudNodeSelectorService {
}
async fetchAliasNodeId(alias: string): Promise<string> {
const aliasNodeEntry: any = await this.apiService.nodesApi
.getNode(alias)
.catch((err) => this.handleError(err));
const aliasNodeEntry: any = await this.nodesApi
.getNode(alias)
.catch((err) => this.handleError(err));
return aliasNodeEntry?.entry?.id;
}
@@ -26,7 +26,7 @@ import {
import { Observable, from } from 'rxjs';
import { map, switchMap } from 'rxjs/operators';
import { TaskDetailsCloudModel } from '../../task/start-task/models/task-details-cloud.model';
import { CompleteFormRepresentation } from '@alfresco/js-api';
import { CompleteFormRepresentation, UploadApi } from '@alfresco/js-api';
import { TaskVariableCloud } from '../models/task-variable-cloud.model';
import { BaseCloudService } from '../../services/base-cloud.service';
import { FormContent } from '../../services/form-fields.interfaces';
@@ -36,11 +36,14 @@ import { FormContent } from '../../services/form-fields.interfaces';
})
export class FormCloudService extends BaseCloudService {
uploadApi: UploadApi;
constructor(
apiService: AlfrescoApiService,
appConfigService: AppConfigService
) {
super(apiService, appConfigService);
this.uploadApi = new UploadApi(apiService.getInstance());
}
/**
@@ -99,7 +102,7 @@ export class FormCloudService extends BaseCloudService {
changedConfig.provider = 'ALL';
changedConfig.hostEcm = contentHost.replace('/alfresco', '');
this.apiService.getInstance().setConfig(changedConfig);
return from(this.apiService.getInstance().upload.uploadFile(
return from(this.uploadApi.uploadFile(
file,
'',
nodeId,
@@ -24,18 +24,25 @@ import {
ContentService,
DownloadService
} from '@alfresco/adf-core';
import { Node } from '@alfresco/js-api';
import { AuthenticationApi, Node, UploadApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
})
export class ProcessCloudContentService {
uploadApi: UploadApi;
authenticationApi: AuthenticationApi;
constructor(
private apiService: AlfrescoApiService,
private logService: LogService,
public contentService: ContentService,
private downloadService: DownloadService
) {}
) {
this.uploadApi = new UploadApi(this.apiService.getInstance());
this.authenticationApi = new AuthenticationApi(this.apiService.getInstance());
}
createTemporaryRawRelatedContent(
file: File,
@@ -43,9 +50,7 @@ export class ProcessCloudContentService {
): Observable<Node> {
return from(
this.apiService
.getInstance()
.upload.uploadFile(file, '', nodeId, '', { overwrite: true })
this.uploadApi.uploadFile(file, '', nodeId, '', { overwrite: true })
).pipe(
map((res: any) => {
return {
@@ -74,8 +79,7 @@ export class ProcessCloudContentService {
}
async getAuthTicket(): Promise<string> {
const { auth } = this.apiService.getInstance();
const ticket = await auth.authenticationApi.getTicket();
const ticket = await this.authenticationApi.getTicket();
if (ticket && ticket.entry) {
return ticket.entry.id || '';
@@ -92,7 +92,7 @@ describe('ProcessAttachmentListComponent', () => {
};
getProcessRelatedContentSpy = spyOn(service, 'getProcessRelatedContent').and.returnValue(of(mockAttachment));
spyOn(service, 'deleteRelatedContent').and.returnValue(of({successCode: true}));
spyOn(service, 'deleteRelatedContent').and.returnValue(of({ successCode: true }));
const blobObj = new Blob();
spyOn(service, 'getFileRawContent').and.returnValue(of(blobObj));
@@ -128,7 +128,7 @@ describe('ProcessAttachmentListComponent', () => {
expect(attachments[0].id).toEqual(mockAttachment.data[0].id);
});
component.ngOnChanges({'taskId': change});
component.ngOnChanges({ 'taskId': change });
});
it('should not attach when no processInstanceId is specified', () => {
@@ -192,7 +192,7 @@ describe('ProcessAttachmentListComponent', () => {
'data': []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'processInstanceId': change});
component.ngOnChanges({ 'processInstanceId': change });
fixture.detectChanges();
await fixture.whenStable();
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim()).toEqual('ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER');
@@ -206,7 +206,7 @@ describe('ProcessAttachmentListComponent', () => {
'data': []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'processInstanceId': change});
component.ngOnChanges({ 'processInstanceId': change });
component.disabled = true;
fixture.detectChanges();
@@ -223,20 +223,20 @@ describe('ProcessAttachmentListComponent', () => {
'data': []
}));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'processInstanceId': change});
component.ngOnChanges({ 'processInstanceId': change });
component.disabled = true;
fixture.detectChanges();
await fixture.whenStable();
expect(fixture.nativeElement.querySelector('div[adf-empty-list-header]').innerText.trim())
.toEqual('ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER');
.toEqual('ADF_PROCESS_LIST.PROCESS-ATTACHMENT.EMPTY.HEADER');
});
it('should not show the empty list component when the attachments list is not empty for completed process', async () => {
getProcessRelatedContentSpy.and.returnValue(of(mockAttachment));
const change = new SimpleChange(null, '123', true);
component.ngOnChanges({'processInstanceId': change});
component.ngOnChanges({ 'processInstanceId': change });
component.disabled = true;
fixture.detectChanges();
@@ -248,9 +248,9 @@ describe('ProcessAttachmentListComponent', () => {
getProcessRelatedContentSpy.and.returnValue(of(mockAttachment));
const change = new SimpleChange(null, '123', true);
const isRelatedContent = 'true';
component.ngOnChanges({'processInstanceId': change});
component.ngOnChanges({ 'processInstanceId': change });
expect(getProcessRelatedContentSpy).toHaveBeenCalled();
expect(getProcessRelatedContentSpy).toHaveBeenCalledWith('123', isRelatedContent);
expect(getProcessRelatedContentSpy).toHaveBeenCalledWith('123', { isRelatedContent });
});
describe('change detection', () => {
@@ -266,7 +266,8 @@ describe('ProcessAttachmentListComponent', () => {
it('should fetch new attachments when processInstanceId changed', () => {
component.ngOnChanges({ 'processInstanceId': change });
expect(getProcessRelatedContentSpy).toHaveBeenCalledWith('456', 'true');
const isRelatedContent = 'true';
expect(getProcessRelatedContentSpy).toHaveBeenCalledWith('456', { isRelatedContent });
});
it('should NOT fetch new attachments when empty changeset made', () => {
@@ -283,12 +284,12 @@ describe('ProcessAttachmentListComponent', () => {
@Component({
template: `
<adf-process-attachment-list>
<adf-empty-list>
<div adf-empty-list-header class="adf-empty-list-header">Custom header</div>
</adf-empty-list>
</adf-process-attachment-list>
`
<adf-process-attachment-list>
<adf-empty-list>
<div adf-empty-list-header class="adf-empty-list-header">Custom header</div>
</adf-empty-list>
</adf-process-attachment-list>
`
})
class CustomEmptyTemplateComponent {
}
@@ -302,7 +303,7 @@ describe('Custom CustomEmptyTemplateComponent', () => {
ProcessTestingModule
],
declarations: [CustomEmptyTemplateComponent],
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
schemas: [CUSTOM_ELEMENTS_SCHEMA]
});
beforeEach(() => {

Some files were not shown because too many files have changed in this diff Show More