diff --git a/demo-shell/src/app/components/process-service/process-service.component.ts b/demo-shell/src/app/components/process-service/process-service.component.ts index ec90548e53..291e247d4d 100644 --- a/demo-shell/src/app/components/process-service/process-service.component.ts +++ b/demo-shell/src/app/components/process-service/process-service.component.ts @@ -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(); + 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('adf-start-process.name'); this.defaultProcessDefinitionName = this.appConfig.get('adf-start-process.processDefinitionName'); this.defaultTaskName = this.appConfig.get('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'; diff --git a/lib/content-services/src/lib/aspect-list/aspect-list.service.spec.ts b/lib/content-services/src/lib/aspect-list/aspect-list.service.spec.ts deleted file mode 100644 index 5f5451af03..0000000000 --- a/lib/content-services/src/lib/aspect-list/aspect-list.service.spec.ts +++ /dev/null @@ -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 = 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() - } - } 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(); - }); - }); - }); - -}); diff --git a/lib/content-services/src/lib/aspect-list/aspect-list.service.ts b/lib/content-services/src/lib/aspect-list/aspect-list.service.ts index adc3722e57..80ac9a57cf 100644 --- a/lib/content-services/src/lib/aspect-list/aspect-list.service.ts +++ b/lib/content-services/src/lib/aspect-list/aspect-list.service.ts @@ -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 { @@ -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) => { diff --git a/lib/content-services/src/lib/content-metadata/services/content-metadata.service.spec.ts b/lib/content-services/src/lib/content-metadata/services/content-metadata.service.spec.ts index 8abb5c0f8f..fa04715a4f 100644 --- a/lib/content-services/src/lib/content-metadata/services/content-metadata.service.spec.ts +++ b/lib/content-services/src/lib/content-metadata/services/content-metadata.service.spec.ts @@ -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); }); diff --git a/lib/content-services/src/lib/content-metadata/services/property-descriptors.service.spec.ts b/lib/content-services/src/lib/content-metadata/services/property-descriptors.service.spec.ts index 2223440df3..e20a93abaa 100644 --- a/lib/content-services/src/lib/content-metadata/services/property-descriptors.service.spec.ts +++ b/lib/content-services/src/lib/content-metadata/services/property-descriptors.service.spec.ts @@ -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', () => { diff --git a/lib/content-services/src/lib/content-metadata/services/property-descriptors.service.ts b/lib/content-services/src/lib/content-metadata/services/property-descriptors.service.ts index be64845ef2..79bf0b3967 100644 --- a/lib/content-services/src/lib/content-metadata/services/property-descriptors.service.ts +++ b/lib/content-services/src/lib/content-metadata/services/property-descriptors.service.ts @@ -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 { 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) diff --git a/lib/content-services/src/lib/content-node-share/content-node-share.directive.ts b/lib/content-services/src/lib/content-node-share/content-node-share.directive.ts index c123d20755..c25d13b6bc 100644 --- a/lib/content-services/src/lib/content-node-share/content-node-share.directive.ts +++ b/lib/content-services/src/lib/content-node-share/content-node-share.directive.ts @@ -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(); + 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 { + private getNodeInfo(nodeId: string): Observable { 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, { diff --git a/lib/content-services/src/lib/content-type/content-type.service.spec.ts b/lib/content-services/src/lib/content-type/content-type.service.spec.ts deleted file mode 100644 index dec00be75d..0000000000 --- a/lib/content-services/src/lib/content-type/content-type.service.spec.ts +++ /dev/null @@ -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(); - }); - }); - -}); diff --git a/lib/content-services/src/lib/content-type/content-type.service.ts b/lib/content-services/src/lib/content-type/content-type.service.ts index 2446e72857..a97d7c5d47 100644 --- a/lib/content-services/src/lib/content-type/content-type.service.ts +++ b/lib/content-services/src/lib/content-type/content-type.service.ts @@ -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 { - return from(this.alfrescoApiService.typesApi.getType(prefixedType)); + return from(this.typesApi.getType(prefixedType)); } getContentTypeChildren(nodeType: string): Observable { @@ -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) ); } diff --git a/lib/content-services/src/lib/dialogs/library/library.dialog.spec.ts b/lib/content-services/src/lib/dialogs/library/library.dialog.spec.ts index f1faae21bd..b0c73c1ea6 100644 --- a/lib/content-services/src/lib/dialogs/library/library.dialog.spec.ts +++ b/lib/content-services/src/lib/dialogs/library/library.dialog.spec.ts @@ -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; 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(() => { diff --git a/lib/content-services/src/lib/dialogs/library/library.dialog.ts b/lib/content-services/src/lib/dialogs/library/library.dialog.ts index 5f518d2aed..274b7e611b 100644 --- a/lib/content-services/src/lib/dialogs/library/library.dialog.ts +++ b/lib/content-services/src/lib/dialogs/library/library.dialog.ts @@ -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 = new EventEmitter(); + /** Emitted when an error occurs. */ + @Output() + error: EventEmitter = new EventEmitter(); - /** 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 = new EventEmitter(); + /** 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 = new EventEmitter(); - onDestroy$: Subject = new Subject(); + onDestroy$: Subject = new Subject(); - 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 - ) {} - - 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 + ) { + 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 { - const { title, id, description, visibility } = this; - const siteBody = { - 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 { - 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 { + const { title, id, description, visibility } = this; + const siteBody = { + 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 { + 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); + }); + }; + } } diff --git a/lib/content-services/src/lib/dialogs/node-lock.dialog.spec.ts b/lib/content-services/src/lib/dialogs/node-lock.dialog.spec.ts index d579df4e72..a95e7a6483 100644 --- a/lib/content-services/src/lib/dialogs/node-lock.dialog.spec.ts +++ b/lib/content-services/src/lib/dialogs/node-lock.dialog.spec.ts @@ -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; 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(); diff --git a/lib/content-services/src/lib/dialogs/node-lock.dialog.ts b/lib/content-services/src/lib/dialogs/node-lock.dialog.ts index c520806b3f..00d48941f9 100644 --- a/lib/content-services/src/lib/dialogs/node-lock.dialog.ts +++ b/lib/content-services/src/lib/dialogs/node-lock.dialog.ts @@ -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, @@ -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 { - 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 { diff --git a/lib/content-services/src/lib/document-list/components/document-list.component.spec.ts b/lib/content-services/src/lib/document-list/components/document-list.component.spec.ts index 506c05e8f7..092701070a 100644 --- a/lib/content-services/src/lib/document-list/components/document-list.component.spec.ts +++ b/lib/content-services/src/lib/document-list/components/document-list.component.spec.ts @@ -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'; diff --git a/lib/content-services/src/lib/document-list/components/document-list.component.ts b/lib/content-services/src/lib/document-list/components/document-list.component.ts index 8f8cfff1e2..09663f08ce 100644 --- a/lib/content-services/src/lib/document-list/components/document-list.component.ts +++ b/lib/content-services/src/lib/document-list/components/document-list.component.ts @@ -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(); + 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); }); diff --git a/lib/content-services/src/lib/document-list/services/custom-resources.service.ts b/lib/content-services/src/lib/document-list/services/custom-resources.service.ts index 7a08c0866d..69b0deea37 100644 --- a/lib/content-services/src/lib/document-list/services/custom-resources.service.ts +++ b/lib/content-services/src/lib/document-list/services/custom-resources.service.ts @@ -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()); } /** diff --git a/lib/content-services/src/lib/document-list/services/document-list.service.spec.ts b/lib/content-services/src/lib/document-list/services/document-list.service.spec.ts index 6086dd964d..35daf7ed11 100644 --- a/lib/content-services/src/lib/document-list/services/document-list.service.spec.ts +++ b/lib/content-services/src/lib/document-list/services/document-list.service.spec.ts @@ -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']); diff --git a/lib/content-services/src/lib/document-list/services/document-list.service.ts b/lib/content-services/src/lib/document-list/services/document-list.service.ts index 6c0ab6f5ad..3681cee899 100644 --- a/lib/content-services/src/lib/document-list/services/document-list.service.ts +++ b/lib/content-services/src/lib/document-list/services/document-list.service.ts @@ -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 { - 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 { - 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 { - 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)) ); } diff --git a/lib/content-services/src/lib/group/services/group.service.ts b/lib/content-services/src/lib/group/services/group.service.ts index 437d3a874c..61d302a022 100644 --- a/lib/content-services/src/lib/group/services/group.service.ts +++ b/lib/content-services/src/lib/group/services/group.service.ts @@ -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 { - 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; diff --git a/lib/content-services/src/lib/permission-manager/services/node-permission.service.ts b/lib/content-services/src/lib/permission-manager/services/node-permission.service.ts index a1c1f78b0b..810b0efd1a 100644 --- a/lib/content-services/src/lib/permission-manager/services/node-permission.service.ts +++ b/lib/content-services/src/lib/permission-manager/services/node-permission.service.ts @@ -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 { - 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 { - 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 { - 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 { - 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 }; + } } diff --git a/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.spec.ts b/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.spec.ts index 73040737d7..9051030862 100644 --- a/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.spec.ts +++ b/lib/content-services/src/lib/search/components/search-filter-container/search-filter-container.component.spec.ts @@ -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; 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(() => { diff --git a/lib/content-services/src/lib/search/services/base-query-builder.service.ts b/lib/content-services/src/lib/search/services/base-query-builder.service.ts index a93b2a18c3..d99eb4500d 100644 --- a/lib/content-services/src/lib/search/services/base-query-builder.service.ts +++ b/lib/content-services/src/lib/search/services/base-query-builder.service.ts @@ -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 { - 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[] { diff --git a/lib/content-services/src/lib/search/services/search-header-query-builder.service.spec.ts b/lib/content-services/src/lib/search/services/search-header-query-builder.service.spec.ts index a4fa2d00e6..a95bca3685 100644 --- a/lib/content-services/src/lib/search/services/search-header-query-builder.service.spec.ts +++ b/lib/content-services/src/lib/search/services/search-header-query-builder.service.spec.ts @@ -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 => { diff --git a/lib/content-services/src/lib/social/services/rating.service.ts b/lib/content-services/src/lib/social/services/rating.service.ts index 33208bfdf2..d19b332699 100644 --- a/lib/content-services/src/lib/social/services/rating.service.ts +++ b/lib/content-services/src/lib/social/services/rating.service.ts @@ -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 { - 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 { - return from(this.apiService.getInstance().core.ratingsApi.removeRating(nodeId, ratingType)) + return from(this.ratingsApi.deleteRating(nodeId, ratingType)) .pipe( catchError(this.handleError) ); diff --git a/lib/content-services/src/lib/tag/services/tag.service.ts b/lib/content-services/src/lib/tag/services/tag.service.ts index 8f1e815461..5811134d9d 100644 --- a/lib/content-services/src/lib/tag/services/tag.service.ts +++ b/lib/content-services/src/lib/tag/services/tag.service.ts @@ -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 { - 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 { - 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 { - 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); diff --git a/lib/content-services/src/lib/upload/components/upload-button.component.spec.ts b/lib/content-services/src/lib/upload/components/upload-button.component.spec.ts index 7e982698cb..571d21ea0e 100644 --- a/lib/content-services/src/lib/upload/components/upload-button.component.spec.ts +++ b/lib/content-services/src/lib/upload/components/upload-button.component.spec.ts @@ -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); diff --git a/lib/content-services/src/lib/version-manager/version-list.component.spec.ts b/lib/content-services/src/lib/version-manager/version-list.component.spec.ts index db7181b274..48fe5ec657 100644 --- a/lib/content-services/src/lib/version-manager/version-list.component.spec.ts +++ b/lib/content-services/src/lib/version-manager/version-list.component.spec.ts @@ -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; - 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 = { id: nodeId, allowableOperations: ['update'] }; spyOn(component, 'downloadContent').and.stub(); - spyOn(alfrescoApiService.nodesApi, 'getNodeInfo').and.returnValue(Promise.resolve( { id: 'nodeInfoId' })); + spyOn(component['nodesApi'], 'getNode').and.returnValue(Promise.resolve( { 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 = { 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 = { id: nodeId, allowableOperations: ['update', 'delete'] }; - spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and.callFake(() => { + spyOn(component['versionsApi'], 'listVersionHistory').and.callFake(() => { return Promise.resolve(new VersionPaging({ list: { entries: [ diff --git a/lib/content-services/src/lib/version-manager/version-list.component.ts b/lib/content-services/src/lib/version-manager/version-list.component.ts index 416cf1371f..1a9440b2a3 100644 --- a/lib/content-services/src/lib/version-manager/version-list.component.ts +++ b/lib/content-services/src/lib/version-manager/version-list.component.ts @@ -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'); } diff --git a/lib/content-services/src/lib/version-manager/version-manager.component.spec.ts b/lib/content-services/src/lib/version-manager/version-manager.component.spec.ts index a539dad183..098a4de404 100644 --- a/lib/content-services/src/lib/version-manager/version-manager.component.spec.ts +++ b/lib/content-services/src/lib/version-manager/version-manager.component.spec.ts @@ -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 ] }}))); }); diff --git a/lib/content-services/src/lib/webscript/webscript.component.ts b/lib/content-services/src/lib/webscript/webscript.component.ts index e45692854f..86ead4b3d1 100644 --- a/lib/content-services/src/lib/webscript/webscript.component.ts +++ b/lib/content-services/src/lib/webscript/webscript.component.ts @@ -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'; /** * ((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; diff --git a/lib/core/dialogs/download-zip/download-zip.dialog.ts b/lib/core/dialogs/download-zip/download-zip.dialog.ts index 222a2f1733..05e2258fe1 100755 --- a/lib/core/dialogs/download-zip/download-zip.dialog.ts +++ b/lib/core/dialogs/download-zip/download-zip.dialog.ts @@ -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); }); diff --git a/lib/core/directives/library-favorite.directive.spec.ts b/lib/core/directives/library-favorite.directive.spec.ts index e0d34253ca..6b2d917439 100644 --- a/lib/core/directives/library-favorite.directive.spec.ts +++ b/lib/core/directives/library-favorite.directive.spec.ts @@ -36,7 +36,6 @@ class TestComponent { describe('LibraryFavoriteDirective', () => { let fixture: ComponentFixture; - 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(); }); }); diff --git a/lib/core/directives/library-favorite.directive.ts b/lib/core/directives/library-favorite.directive.ts index f511e3014a..60c7758ee2 100644 --- a/lib/core/directives/library-favorite.directive.ts +++ b/lib/core/directives/library-favorite.directive.ts @@ -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(); 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); diff --git a/lib/core/directives/library-membership.directive.spec.ts b/lib/core/directives/library-membership.directive.spec.ts index 0e225c2054..6524768f4a 100644 --- a/lib/core/directives/library-membership.directive.spec.ts +++ b/lib/core/directives/library-membership.directive.spec.ts @@ -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(() => { diff --git a/lib/core/directives/library-membership.directive.ts b/lib/core/directives/library-membership.directive.ts index 59c4ba88e2..754090fbf6 100644 --- a/lib/core/directives/library-membership.directive.ts +++ b/lib/core/directives/library-membership.directive.ts @@ -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 = new BehaviorSubject(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)); } } diff --git a/lib/core/directives/node-delete.directive.spec.ts b/lib/core/directives/node-delete.directive.spec.ts index e49892ced7..94a92d481d 100644 --- a/lib/core/directives/node-delete.directive.spec.ts +++ b/lib/core/directives/node-delete.directive.spec.ts @@ -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(); }); }); diff --git a/lib/core/directives/node-delete.directive.ts b/lib/core/directives/node-delete.directive.ts index f33430419a..ca697fd7a2 100644 --- a/lib/core/directives/node-delete.directive.ts +++ b/lib/core/directives/node-delete.directive.ts @@ -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 = 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; 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( diff --git a/lib/core/directives/node-download.directive.spec.ts b/lib/core/directives/node-download.directive.spec.ts index a01d1c62dc..3b8d008c39 100755 --- a/lib/core/directives/node-download.directive.spec.ts +++ b/lib/core/directives/node-download.directive.spec.ts @@ -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: '
' }) 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'); }); diff --git a/lib/core/directives/node-download.directive.ts b/lib/core/directives/node-download.directive.ts index 47387c122a..79bb0c4c8b 100755 --- a/lib/core/directives/node-download.directive.ts +++ b/lib/core/directives/node-download.directive.ts @@ -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 = ( 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; } diff --git a/lib/core/directives/node-favorite.directive.spec.ts b/lib/core/directives/node-favorite.directive.spec.ts index dbef29872e..d9707961ae 100644 --- a/lib/core/directives/node-favorite.directive.spec.ts +++ b/lib/core/directives/node-favorite.directive.spec.ts @@ -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' } } diff --git a/lib/core/directives/node-favorite.directive.ts b/lib/core/directives/node-favorite.directive.ts index 696749ca5c..9446a5c10d 100644 --- a/lib/core/directives/node-favorite.directive.ts +++ b/lib/core/directives/node-favorite.directive.ts @@ -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 = ( 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-', body)) + from(this.favoritesApi.createFavorite('-me-', 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; - const id = ( node).nodeId || node.id; + const id = ( node).nodeId || node.id; - const promise = this.alfrescoApiService.favoritesApi.getFavorite('-me-', id); + const promise = this.favoritesApi.getFavorite('-me-', id); return from(promise).pipe( map(() => ({ diff --git a/lib/core/directives/node-restore.directive.spec.ts b/lib/core/directives/node-restore.directive.spec.ts index 68170f371c..a6b0d667c2 100644 --- a/lib/core/directives/node-restore.directive.spec.ts +++ b/lib/core/directives/node-restore.directive.spec.ts @@ -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; 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(); }); }); diff --git a/lib/core/directives/node-restore.directive.ts b/lib/core/directives/node-restore.directive.ts index 7d7b26928e..1f4791ddf4 100644 --- a/lib/core/directives/node-restore.directive.ts +++ b/lib/core/directives/node-restore.directive.ts @@ -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 { - 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 { const { entry } = node; - const promise = this.alfrescoApiService.getInstance().nodes.restoreNode(entry.id); + const promise = this.trashcanApi.restoreDeletedNode(entry.id); return from(promise).pipe( map(() => ({ diff --git a/lib/core/form/components/widgets/core/form.model.spec.ts b/lib/core/form/components/widgets/core/form.model.spec.ts index ebcf328040..8ac15b8551 100644 --- a/lib/core/form/components/widgets/core/form.model.spec.ts +++ b/lib/core/form/components/widgets/core/form.model.spec.ts @@ -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', () => { diff --git a/lib/core/form/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts b/lib/core/form/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts index 720bd9235f..b31834aac0 100644 --- a/lib/core/form/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts +++ b/lib/core/form/components/widgets/dynamic-table/editors/dropdown/dropdown.editor.spec.ts @@ -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 = {value: {dropdown: 'one'}}; column = { diff --git a/lib/core/form/components/widgets/dynamic-table/editors/row.editor.spec.ts b/lib/core/form/components/widgets/dynamic-table/editors/row.editor.spec.ts index d93291c09a..5bf69850bd 100644 --- a/lib/core/form/components/widgets/dynamic-table/editors/row.editor.spec.ts +++ b/lib/core/form/components/widgets/dynamic-table/editors/row.editor.spec.ts @@ -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 = {}; component.column = {}; }); diff --git a/lib/core/form/components/widgets/functional-group/functional-group.widget.spec.ts b/lib/core/form/components/widgets/functional-group/functional-group.widget.spec.ts index 1e5afecd7e..cb179b0711 100644 --- a/lib/core/form/components/widgets/functional-group/functional-group.widget.spec.ts +++ b/lib/core/form/components/widgets/functional-group/functional-group.widget.spec.ts @@ -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()); diff --git a/lib/core/form/components/widgets/radio-buttons/radio-buttons.widget.spec.ts b/lib/core/form/components/widgets/radio-buttons/radio-buttons.widget.spec.ts index bf12c912b1..90de5eb87a 100644 --- a/lib/core/form/components/widgets/radio-buttons/radio-buttons.widget.spec.ts +++ b/lib/core/form/components/widgets/radio-buttons/radio-buttons.widget.spec.ts @@ -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: '' }); }); diff --git a/lib/core/form/components/widgets/typeahead/typeahead.widget.spec.ts b/lib/core/form/components/widgets/typeahead/typeahead.widget.spec.ts index ceaf1c79d6..25e7bb529a 100644 --- a/lib/core/form/components/widgets/typeahead/typeahead.widget.spec.ts +++ b/lib/core/form/components/widgets/typeahead/typeahead.widget.spec.ts @@ -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'; diff --git a/lib/core/form/services/activiti-alfresco.service.ts b/lib/core/form/services/activiti-alfresco.service.ts index 824868c242..d600b6eee5 100644 --- a/lib/core/form/services/activiti-alfresco.service.ts +++ b/lib/core/form/services/activiti-alfresco.service.ts @@ -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 { - 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 { - 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)) diff --git a/lib/core/form/services/ecm-model.service.ts b/lib/core/form/services/ecm-model.service.ts index 7d32a1b587..35b91f32de 100644 --- a/lib/core/form/services/ecm-model.service.ts +++ b/lib/core/form/services/ecm-model.service.ts @@ -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 { @@ -128,7 +132,7 @@ export class EcmModelService { } public activeEcmModel(modelName: string): Observable { - 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 { - 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 { - 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 { - 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 { 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)) diff --git a/lib/core/form/services/form.service.spec.ts b/lib/core/form/services/form.service.spec.ts index 886bb79211..0ff4b39eb7 100644 --- a/lib/core/form/services/form.service.spec.ts +++ b/lib/core/form/services/form.service.spec.ts @@ -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) => { diff --git a/lib/core/form/services/form.service.ts b/lib/core/form/services/form.service.ts index b5e8597a5d..4a143fda02 100644 --- a/lib/core/form/services/form.service.ts +++ b/lib/core/form/services/form.service.ts @@ -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(); formDataRefreshed = new Subject(); formFieldValueChanged = new Subject(); @@ -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 { - 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 { const 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 => response.data || []), map((user) => { diff --git a/lib/core/form/services/process-content.service.ts b/lib/core/form/services/process-content.service.ts index 5665fe9f76..8e0f7a9525 100644 --- a/lib/core/form/services/process-content.service.ts +++ b/lib/core/form/services/process-content.service.ts @@ -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 { 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 { - return from(this.contentApi.getContentThumbnail(contentId)) + return from(this.contentApi.getRawContent(contentId, 'thumbnail')) .pipe(catchError((err) => this.handleError(err))); } diff --git a/lib/core/form/services/widget-visibility.service.ts b/lib/core/form/services/widget-visibility.service.ts index 4991ca116d..d9078b3ddd 100644 --- a/lib/core/form/services/widget-visibility.service.ts +++ b/lib/core/form/services/widget-visibility.service.ts @@ -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 { - return from(this.apiService.getInstance().activiti.taskFormsApi.getTaskFormVariables(taskId)) + return from(this.taskFormsApi.getTaskFormVariables(taskId)) .pipe( map((res) => { const jsonRes = this.toJson(res); diff --git a/lib/core/mock/search.service.mock.ts b/lib/core/mock/search.service.mock.ts index 3c6adebd14..cd68d988e0 100644 --- a/lib/core/mock/search.service.mock.ts +++ b/lib/core/mock/search.service.mock.ts @@ -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) + }; diff --git a/lib/core/services/alfresco-api.service.ts b/lib/core/services/alfresco-api.service.ts index a44419d915..d0652b230f 100644 --- a/lib/core/services/alfresco-api.service.ts +++ b/lib/core/services/alfresco-api.service.ts @@ -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 = 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); } } diff --git a/lib/core/services/apps-process.service.ts b/lib/core/services/apps-process.service.ts index e927ab0bfc..0f3c62e55f 100644 --- a/lib/core/services/apps-process.service.ts +++ b/lib/core/services/apps-process.service.ts @@ -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 { - return from(this.apiService.getInstance().activiti.appsApi.getAppDefinitions()) + return from(this.appsApi.getAppDefinitions()) .pipe( map((response: any) => response.data), catchError((err) => this.handleError(err)) @@ -49,7 +52,7 @@ export class AppsProcessService { * @returns The list of deployed apps */ getDeployedApplicationsByName(name: string): Observable { - return from(this.apiService.getInstance().activiti.appsApi.getAppDefinitions()) + return from(this.appsApi.getAppDefinitions()) .pipe( map((response: any) => 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 { - 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)) diff --git a/lib/core/services/authentication.service.spec.ts b/lib/core/services/authentication.service.spec.ts index 1bcb2c14f8..6a922ff101 100644 --- a/lib/core/services/authentication.service.spec.ts +++ b/lib/core/services/authentication.service.spec.ts @@ -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(( { - 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); diff --git a/lib/core/services/authentication.service.ts b/lib/core/services/authentication.service.ts index da9fe9c929..59623b7b07 100644 --- a/lib/core/services/authentication.service.ts +++ b/lib/core/services/authentication.service.ts @@ -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 = new ReplaySubject(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 { - return from(this.alfrescoApi.getInstance().activiti.profileApi.getProfile()); + return from(this.profileApi.getProfile()); } private hasValidRedirection(provider: string): boolean { diff --git a/lib/core/services/bpm-user.service.ts b/lib/core/services/bpm-user.service.ts index 95d1ae3c29..5197d08aa7 100644 --- a/lib/core/services/bpm-user.service.ts +++ b/lib/core/services/bpm-user.service.ts @@ -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 { - 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(); } /** diff --git a/lib/core/services/comment-content.service.ts b/lib/core/services/comment-content.service.ts index 415b1b9c4f..c74983b2f0 100644 --- a/lib/core/services/comment-content.service.ts +++ b/lib/core/services/comment-content.service.ts @@ -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 { - 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 { - return from(this.apiService.getInstance().core.commentsApi.getComments(nodeId)) + return from(this.commentsApi.listComments(nodeId)) .pipe( map((response) => { const comments: CommentModel[] = []; diff --git a/lib/core/services/comment-process.service.spec.ts b/lib/core/services/comment-process.service.spec.ts index 3e24807647..26ad894259 100644 --- a/lib/core/services/comment-process.service.spec.ts +++ b/lib/core/services/comment-process.service.spec.ts @@ -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)); }); diff --git a/lib/core/services/comment-process.service.ts b/lib/core/services/comment-process.service.ts index 73cd08ed2e..cc65df6701 100644 --- a/lib/core/services/comment-process.service.ts +++ b/lib/core/services/comment-process.service.ts @@ -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 { - 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 { - 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 { - 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 { return from( - this.apiService.getInstance().activiti.commentsApi.addProcessInstanceComment({ message: message }, processInstanceId) + this.commentsApi.addProcessInstanceComment({ message: message }, processInstanceId) ).pipe( map((response) => { return new CommentModel({ diff --git a/lib/core/services/content.service.ts b/lib/core/services/content.service.ts index 2cfb5243d5..5ae5f8c081 100644 --- a/lib/core/services/content.service.ts +++ b/lib/core/services/content.service.ts @@ -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 = new Subject(); folderEdit: Subject = new Subject(); + 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 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 { - 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 { - 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 { diff --git a/lib/core/services/deleted-nodes-api.service.ts b/lib/core/services/deleted-nodes-api.service.ts index a94d8b7065..ade5e39e58 100644 --- a/lib/core/services/deleted-nodes-api.service.ts +++ b/lib/core/services/deleted-nodes-api.service.ts @@ -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)) diff --git a/lib/core/services/discovery-api.service.spec.ts b/lib/core/services/discovery-api.service.spec.ts deleted file mode 100644 index 6d9e0c1421..0000000000 --- a/lib/core/services/discovery-api.service.spec.ts +++ /dev/null @@ -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(''); - }); - }); -}); diff --git a/lib/core/services/discovery-api.service.ts b/lib/core/services/discovery-api.service.ts index fb0d76d3ca..d738bddad0 100644 --- a/lib/core/services/discovery-api.service.ts +++ b/lib/core/services/discovery-api.service.ts @@ -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 { - 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 { - 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 { - return from(this.systemPropertiesApi.getProperties()) + const systemPropertiesApi = new SystemPropertiesApi(this.apiService.getInstance()); + + return from(systemPropertiesApi.getProperties()) .pipe( map((res) => { if ('string' === typeof (res)) { diff --git a/lib/core/services/download-zip.service.ts b/lib/core/services/download-zip.service.ts index b13fbbdc14..021830507d 100755 --- a/lib/core/services/download-zip.service.ts +++ b/lib/core/services/download-zip.service.ts @@ -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 { - 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 { - 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 { - 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) { diff --git a/lib/core/services/favorites-api.service.ts b/lib/core/services/favorites-api.service.ts index a3c9d9ab2c..803ee3ce31 100644 --- a/lib/core/services/favorites-api.service.ts +++ b/lib/core/services/favorites-api.service.ts @@ -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 { 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( diff --git a/lib/core/services/lock.service.ts b/lib/core/services/lock.service.ts index ac5c7a9fb3..9d4e48dec7 100644 --- a/lib/core/services/lock.service.ts +++ b/lib/core/services/lock.service.ts @@ -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)) { diff --git a/lib/core/services/nodes-api.service.spec.ts b/lib/core/services/nodes-api.service.spec.ts deleted file mode 100644 index 743eb284ad..0000000000 --- a/lib/core/services/nodes-api.service.spec.ts +++ /dev/null @@ -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( 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( 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( 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(); - }); - }); -}); diff --git a/lib/core/services/nodes-api.service.ts b/lib/core/services/nodes-api.service.ts index aff09288c5..3a21b4b0f8 100644 --- a/lib/core/services/nodes-api.service.ts +++ b/lib/core/services/nodes-api.service.ts @@ -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 { 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 { - 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 { 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 { - 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() { diff --git a/lib/core/services/page-title.service.spec.ts b/lib/core/services/page-title.service.spec.ts deleted file mode 100644 index b47af4935c..0000000000 --- a/lib/core/services/page-title.service.spec.ts +++ /dev/null @@ -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'); - - ( titleService).setTitle.calls.reset(); - - translationService.translate.onLangChange.next( {}); - // 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'); - - ( titleService).setTitle.calls.reset(); - - translationService.translate.onTranslationChange.next( {}); - // cspell: disable-next - expect(titleServiceSpy).toHaveBeenCalledWith('привет - My application'); - }); -}); diff --git a/lib/core/services/people-content.service.spec.ts b/lib/core/services/people-content.service.spec.ts index a37acebd3f..88bbf2a45f 100644 --- a/lib/core/services/people-content.service.spec.ts +++ b/lib/core/services/people-content.service.spec.ts @@ -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); diff --git a/lib/core/services/people-content.service.ts b/lib/core/services/people-content.service.ts index 6a3a5300b6..8ed58c74db 100644 --- a/lib/core/services/people-content.service.ts +++ b/lib/core/services/people-content.service.ts @@ -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()); } /** diff --git a/lib/core/services/people-process.service.ts b/lib/core/services/people-process.service.ts index 760772bc10..ae9bd57711 100644 --- a/lib/core/services/people-process.service.ts +++ b/lib/core/services/people-process.service.ts @@ -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 { - 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 { - 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 { + 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); } /** diff --git a/lib/core/services/renditions.service.ts b/lib/core/services/renditions.service.ts index 3c67919054..fea5a3a482 100644 --- a/lib/core/services/renditions.service.ts +++ b/lib/core/services/renditions.service.ts @@ -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 { - 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 { - 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 { - 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 })); } /** diff --git a/lib/core/services/search.service.spec.ts b/lib/core/services/search.service.spec.ts index 5ad40aef12..e88a5c8cfa 100644 --- a/lib/core/services/search.service.spec.ts +++ b/lib/core/services/search.service.spec.ts @@ -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) => { diff --git a/lib/core/services/search.service.ts b/lib/core/services/search.service.ts index 74e557b995..d69c90b877 100644 --- a/lib/core/services/search.service.ts +++ b/lib/core/services/search.service.ts @@ -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 = 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 { - 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 { 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 { - const promise = this.apiService.getInstance().search.searchApi.search(queryBody); + const promise = this.searchApi.search(queryBody); promise.then((nodePaging: NodePaging) => { this.dataLoaded.next(nodePaging); diff --git a/lib/core/services/shared-links-api.service.ts b/lib/core/services/shared-links-api.service.ts index 0c2be17bd5..7f62c03be1 100644 --- a/lib/core/services/shared-links-api.service.ts +++ b/lib/core/services/shared-links-api.service.ts @@ -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 { - const promise = this.sharedLinksApi.addSharedLink({ nodeId: nodeId }, options); + const promise = this.sharedLinksApi.createSharedLink({ nodeId: nodeId }, options); return from(promise).pipe( catchError((err) => of(err)) diff --git a/lib/core/services/sites.service.ts b/lib/core/services/sites.service.ts index d4a4573dc8..bc94a44b93 100644 --- a/lib/core/services/sites.service.ts +++ b/lib/core/services/sites.service.ts @@ -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()); } /** diff --git a/lib/core/services/thumbnail.service.spec.ts b/lib/core/services/thumbnail.service.spec.ts index 355535fdc4..3dd1b288e6 100644 --- a/lib/core/services/thumbnail.service.spec.ts +++ b/lib/core/services/thumbnail.service.spec.ts @@ -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'); }); }); diff --git a/lib/core/services/thumbnail.service.ts b/lib/core/services/thumbnail.service.ts index 010d246d39..a57b04423e 100644 --- a/lib/core/services/thumbnail.service.ts +++ b/lib/core/services/thumbnail.service.ts @@ -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; diff --git a/lib/core/services/upload.service.spec.ts b/lib/core/services/upload.service.spec.ts index f197a9bb34..365f21d898 100644 --- a/lib/core/services/upload.service.spec.ts +++ b/lib/core/services/upload.service.spec.ts @@ -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(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( { name: 'fake-name', size: 10 }, { diff --git a/lib/core/services/upload.service.ts b/lib/core/services/upload.service.ts index 5648fe0f1c..d1de1d4664 100644 --- a/lib/core/services/upload.service.ts +++ b/lib/core/services/upload.service.ts @@ -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 = new Subject(); fileUpload: Subject = new Subject(); - fileUploadStarting: Subject = new Subject< - FileUploadEvent - >(); - fileUploadCancelled: Subject = new Subject< - FileUploadEvent - >(); - fileUploadProgress: Subject = new Subject< - FileUploadEvent - >(); - fileUploadAborted: Subject = new Subject< - FileUploadEvent - >(); - fileUploadError: Subject = new Subject< - FileUploadErrorEvent - >(); - fileUploadComplete: Subject = new Subject< - FileUploadCompleteEvent - >(); - fileUploadDeleted: Subject = new Subject< - FileUploadDeleteEvent - >(); + fileUploadStarting: Subject = new Subject(); + fileUploadCancelled: Subject = new Subject(); + fileUploadProgress: Subject = new Subject(); + fileUploadAborted: Subject = new Subject(); + fileUploadError: Subject = new Subject(); + fileUploadComplete: Subject = new Subject(); + fileUploadDeleted: Subject = new Subject(); fileDeleted: Subject = new Subject(); + 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, 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)); } diff --git a/lib/core/testing/setup-test-bed.ts b/lib/core/testing/setup-test-bed.ts index 0f7f8502fe..f91852f1ac 100644 --- a/lib/core/testing/setup-test-bed.ts +++ b/lib/core/testing/setup-test-bed.ts @@ -44,6 +44,5 @@ export const setupTestBed = (moduleDef: TestModuleMetadata) => { .catch(done.fail); } ); -​ afterAll(() => allowAngularToReset()); }; diff --git a/lib/core/viewer/components/media-player.component.spec.ts b/lib/core/viewer/components/media-player.component.spec.ts deleted file mode 100644 index 6a8010590d..0000000000 --- a/lib/core/viewer/components/media-player.component.spec.ts +++ /dev/null @@ -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; - 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); - })); - }); -}); diff --git a/lib/core/viewer/components/viewer.component.spec.ts b/lib/core/viewer/components/viewer.component.spec.ts index ad705fa9e0..952c75e05a 100644 --- a/lib/core/viewer/components/viewer.component.spec.ts +++ b/lib/core/viewer/components/viewer.component.spec.ts @@ -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', () => { diff --git a/lib/core/viewer/components/viewer.component.ts b/lib/core/viewer/components/viewer.component.ts index 29aba259be..e98c3b153e 100644 --- a/lib/core/viewer/components/viewer.component.ts +++ b/lib/core/viewer/components/viewer.component.ts @@ -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(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); diff --git a/lib/core/viewer/services/view-util.service.ts b/lib/core/viewer/services/view-util.service.ts index bc300c3b5f..020d80babc 100644 --- a/lib/core/viewer/services/view-util.service.ts +++ b/lib/core/viewer/services/view-util.service.ts @@ -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 = new Subject(); urlFileContentChange: Subject = new Subject(); + 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 { - 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 { - 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 { 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 { - 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; diff --git a/lib/insights/src/lib/analytics-process/services/analytics.service.ts b/lib/insights/src/lib/analytics-process/services/analytics.service.ts index 3a7571a2d8..f7cf153418 100644 --- a/lib/insights/src/lib/analytics-process/services/analytics.service.ts +++ b/lib/insights/src/lib/analytics-process/services/analytics.service.ts @@ -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 { - 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 { - 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 { - 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 { - 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 { 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - return from(this.apiService.getInstance().activiti.reportApi.deleteReport(reportId)) + return from(this.reportApi.deleteReport(reportId)) .pipe( map(() => { this.logService.info('delete'); diff --git a/lib/insights/src/lib/diagram/services/diagrams.service.ts b/lib/insights/src/lib/diagram/services/diagrams.service.ts index 81d9f208d8..398bc5ecd1 100644 --- a/lib/insights/src/lib/diagram/services/diagrams.service.ts +++ b/lib/insights/src/lib/diagram/services/diagrams.service.ts @@ -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 { - 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 { - return from(this.apiService.getInstance().activiti.modelJsonBpmnApi.getModelJSONForProcessDefinition(processInstanceId)) + return from(this.modelJsonBpmnApi.getModelJSONForProcessDefinition(processInstanceId)) .pipe( catchError((err) => this.handleError(err)) ); diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/attach-file/attach-file-cloud-widget.component.spec.ts b/lib/process-services-cloud/src/lib/form/components/widgets/attach-file/attach-file-cloud-widget.component.spec.ts index fb6db61eb3..a2055e96e4 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/attach-file/attach-file-cloud-widget.component.spec.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/attach-file/attach-file-cloud-widget.component.spec.ts @@ -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'); diff --git a/lib/process-services-cloud/src/lib/form/components/widgets/attach-file/attach-file-cloud-widget.component.ts b/lib/process-services-cloud/src/lib/form/components/widgets/attach-file/attach-file-cloud-widget.component.ts index fc51b3fd27..43f5136671 100644 --- a/lib/process-services-cloud/src/lib/form/components/widgets/attach-file/attach-file-cloud-widget.component.ts +++ b/lib/process-services-cloud/src/lib/form/components/widgets/attach-file/attach-file-cloud-widget.component.ts @@ -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); diff --git a/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.spec.ts b/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.spec.ts deleted file mode 100644 index 2ab49800d5..0000000000 --- a/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.spec.ts +++ /dev/null @@ -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() - } - })); - - getNodeSpy = spyOn(apiService.nodesApi, 'getNode'); - }); - - it('should be able to open the content node select panel dialog', () => { - const mockData = { - 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'); - }); -}); diff --git a/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.ts b/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.ts index dcfb8cfc1a..3f03e99446 100644 --- a/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.ts +++ b/lib/process-services-cloud/src/lib/form/services/content-cloud-node-selector.service.ts @@ -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 { @@ -55,7 +61,7 @@ export class ContentCloudNodeSelectorService { } async fetchNodeIdFromRelativePath(alias: string, opts: { relativePath: string }): Promise { - 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 { - 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; } diff --git a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts index bbd320042a..3ed8e88e80 100644 --- a/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/form/services/form-cloud.service.ts @@ -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, diff --git a/lib/process-services-cloud/src/lib/form/services/process-cloud-content.service.ts b/lib/process-services-cloud/src/lib/form/services/process-cloud-content.service.ts index c0e5a68191..86fb7256b0 100644 --- a/lib/process-services-cloud/src/lib/form/services/process-cloud-content.service.ts +++ b/lib/process-services-cloud/src/lib/form/services/process-cloud-content.service.ts @@ -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 { 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 { - 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 || ''; diff --git a/lib/process-services/src/lib/attachment/process-attachment-list.component.spec.ts b/lib/process-services/src/lib/attachment/process-attachment-list.component.spec.ts index 75d30a3195..a4dfb72851 100644 --- a/lib/process-services/src/lib/attachment/process-attachment-list.component.spec.ts +++ b/lib/process-services/src/lib/attachment/process-attachment-list.component.spec.ts @@ -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: ` - - -
Custom header
-
-
- ` + + +
Custom header
+
+
+ ` }) class CustomEmptyTemplateComponent { } @@ -302,7 +303,7 @@ describe('Custom CustomEmptyTemplateComponent', () => { ProcessTestingModule ], declarations: [CustomEmptyTemplateComponent], - schemas: [ CUSTOM_ELEMENTS_SCHEMA ] + schemas: [CUSTOM_ELEMENTS_SCHEMA] }); beforeEach(() => { diff --git a/lib/process-services/src/lib/attachment/process-attachment-list.component.ts b/lib/process-services/src/lib/attachment/process-attachment-list.component.ts index 0689495bd9..08287f5f76 100644 --- a/lib/process-services/src/lib/attachment/process-attachment-list.component.ts +++ b/lib/process-services/src/lib/attachment/process-attachment-list.component.ts @@ -15,8 +15,19 @@ * limitations under the License. */ -import { ContentService, EmptyListComponent , ThumbnailService, ProcessContentService } from '@alfresco/adf-core'; -import { AfterContentInit, ContentChild, Component, EventEmitter, Input, NgZone, OnChanges, Output, SimpleChanges, ViewEncapsulation } from '@angular/core'; +import { ContentService, EmptyListComponent, ThumbnailService, ProcessContentService } from '@alfresco/adf-core'; +import { + AfterContentInit, + ContentChild, + Component, + EventEmitter, + Input, + NgZone, + OnChanges, + Output, + SimpleChanges, + ViewEncapsulation +} from '@angular/core'; @Component({ selector: 'adf-process-attachment-list', @@ -110,8 +121,8 @@ export class ProcessAttachmentListComponent implements OnChanges, AfterContentIn if (processInstanceId) { this.reset(); this.isLoading = true; - const opts: string = 'true'; - this.activitiContentService.getProcessRelatedContent(processInstanceId, opts).subscribe( + const isRelatedContent = 'true'; + this.activitiContentService.getProcessRelatedContent(processInstanceId, { isRelatedContent }).subscribe( (res: any) => { res.data.forEach((content) => { this.attachments.push({ diff --git a/lib/process-services/src/lib/attachment/task-attachment-list.component.spec.ts b/lib/process-services/src/lib/attachment/task-attachment-list.component.spec.ts index af22425b5e..a46d7e1b6d 100644 --- a/lib/process-services/src/lib/attachment/task-attachment-list.component.spec.ts +++ b/lib/process-services/src/lib/attachment/task-attachment-list.component.spec.ts @@ -280,9 +280,9 @@ describe('TaskAttachmentList', () => { it('should fetch new attachments when taskId changed', async () => { fixture.detectChanges(); await fixture.whenStable(); - + const isRelatedContent = 'true'; component.ngOnChanges({ 'taskId': change }); - expect(getTaskRelatedContentSpy).toHaveBeenCalledWith('456', 'true'); + expect(getTaskRelatedContentSpy).toHaveBeenCalledWith('456', { isRelatedContent }); }); it('should NOT fetch new attachments when empty change set made', () => { @@ -311,7 +311,7 @@ describe('TaskAttachmentList', () => { expect(deleteContentSpy).toHaveBeenCalled(); }); - }); + }); }); @Component({ diff --git a/lib/process-services/src/lib/attachment/task-attachment-list.component.ts b/lib/process-services/src/lib/attachment/task-attachment-list.component.ts index 516066df03..8604782e26 100644 --- a/lib/process-services/src/lib/attachment/task-attachment-list.component.ts +++ b/lib/process-services/src/lib/attachment/task-attachment-list.component.ts @@ -118,8 +118,8 @@ export class TaskAttachmentListComponent implements OnChanges, AfterContentInit if (taskId) { this.isLoading = true; this.reset(); - const opts = 'true'; - this.activitiContentService.getTaskRelatedContent(taskId, opts).subscribe( + const isRelatedContent = 'true'; + this.activitiContentService.getTaskRelatedContent(taskId, { isRelatedContent }).subscribe( (res: any) => { const attachList = []; res.data.forEach((content) => { diff --git a/lib/process-services/src/lib/content-widget/attach-file-widget-dialog.service.ts b/lib/process-services/src/lib/content-widget/attach-file-widget-dialog.service.ts index d95858208d..948486d13f 100644 --- a/lib/process-services/src/lib/content-widget/attach-file-widget-dialog.service.ts +++ b/lib/process-services/src/lib/content-widget/attach-file-widget-dialog.service.ts @@ -20,7 +20,7 @@ import { EventEmitter, Injectable, Output } from '@angular/core'; import { AlfrescoApiService, TranslationService } from '@alfresco/adf-core'; import { Observable, of, Subject } from 'rxjs'; import { AttachFileWidgetDialogComponentData } from './attach-file-widget-dialog-component.interface'; -import { AlfrescoEndpointRepresentation, Node } from '@alfresco/js-api'; +import { AlfrescoEndpointRepresentation, Node, ContentApi } from '@alfresco/js-api'; import { AttachFileWidgetDialogComponent } from './attach-file-widget-dialog.component'; import { switchMap } from 'rxjs/operators'; @@ -76,13 +76,14 @@ export class AttachFileWidgetDialogService { downloadURL(repository: AlfrescoEndpointRepresentation, sourceId: string): Observable { const { accountIdentifier } = this.constructPayload(repository); + const contentApi = new ContentApi(this.externalApis[accountIdentifier].getInstance()); if (this.externalApis[accountIdentifier]?.getInstance()?.isLoggedIn()) { - return of(this.externalApis[accountIdentifier].contentApi.getContentUrl(sourceId)); + return of(contentApi.getContentUrl(sourceId)); } return this.showExternalHostLoginDialog(repository).pipe( - switchMap(() => of(this.externalApis[accountIdentifier].getInstance().content.getContentUrl(sourceId))) + switchMap(() => of(contentApi.getContentUrl(sourceId))) ); } diff --git a/lib/process-services/src/lib/process-list/services/process-filter.service.spec.ts b/lib/process-services/src/lib/process-list/services/process-filter.service.spec.ts index 121d29ade4..a6e83dc982 100644 --- a/lib/process-services/src/lib/process-list/services/process-filter.service.spec.ts +++ b/lib/process-services/src/lib/process-list/services/process-filter.service.spec.ts @@ -19,15 +19,13 @@ import { TestBed } from '@angular/core/testing'; import { mockError, fakeProcessFiltersResponse } from '../../mock'; import { FilterProcessRepresentationModel } from '../models/filter-process.model'; import { ProcessFilterService } from './process-filter.service'; -import { AlfrescoApiService, setupTestBed, CoreTestingModule } from '@alfresco/adf-core'; +import { setupTestBed, CoreTestingModule } from '@alfresco/adf-core'; declare let jasmine: any; describe('Process filter', () => { let service: ProcessFilterService; - let apiService: AlfrescoApiService; - let alfrescoApi: any; setupTestBed({ imports: [ @@ -36,9 +34,7 @@ describe('Process filter', () => { }); beforeEach(() => { - apiService = TestBed.inject(AlfrescoApiService); service = TestBed.inject(ProcessFilterService); - alfrescoApi = apiService.getInstance(); }); describe('filters', () => { @@ -47,7 +43,7 @@ describe('Process filter', () => { let createFilter: jasmine.Spy; beforeEach(() => { - getFilters = spyOn(alfrescoApi.activiti.userFiltersApi, 'getUserProcessInstanceFilters') + getFilters = spyOn(service['userFiltersApi'], 'getUserProcessInstanceFilters') .and .returnValue(Promise.resolve(fakeProcessFiltersResponse)); @@ -67,7 +63,7 @@ describe('Process filter', () => { it('should call the API with the correct appId when specified', () => { service.getProcessFilters(226); - expect(getFilters).toHaveBeenCalledWith({appId: 226}); + expect(getFilters).toHaveBeenCalledWith({ appId: 226 }); }); it('should return the task filter by id', (done) => { @@ -181,7 +177,8 @@ describe('Process filter', () => { getFilters = getFilters.and.returnValue(Promise.reject(mockError)); service.getProcessFilters(null).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe(mockError); done(); @@ -194,9 +191,9 @@ describe('Process filter', () => { describe('add filter', () => { beforeEach(() => { - createFilter = spyOn(alfrescoApi.activiti.userFiltersApi, 'createUserProcessInstanceFilter') - .and - .callFake((processfilter: FilterProcessRepresentationModel) => Promise.resolve(processfilter)); + createFilter = spyOn(service['userFiltersApi'], 'createUserProcessInstanceFilter') + .and + .callFake((processfilter: FilterProcessRepresentationModel) => Promise.resolve(processfilter)); }); const filter = fakeProcessFiltersResponse.data[0]; @@ -217,7 +214,8 @@ describe('Process filter', () => { createFilter = createFilter.and.returnValue(Promise.reject(mockError)); service.addProcessFilter(filter).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe(mockError); done(); @@ -228,7 +226,8 @@ describe('Process filter', () => { it('should return a default error if no data is returned by the API', (done) => { createFilter = createFilter.and.returnValue(Promise.reject(null)); service.addProcessFilter(filter).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe('Server error'); done(); diff --git a/lib/process-services/src/lib/process-list/services/process-filter.service.ts b/lib/process-services/src/lib/process-list/services/process-filter.service.ts index 779d862183..04d8c93b47 100644 --- a/lib/process-services/src/lib/process-list/services/process-filter.service.ts +++ b/lib/process-services/src/lib/process-list/services/process-filter.service.ts @@ -20,14 +20,17 @@ import { Injectable } from '@angular/core'; import { Observable, from, forkJoin, throwError } from 'rxjs'; import { FilterProcessRepresentationModel } from '../models/filter-process.model'; import { map, catchError } from 'rxjs/operators'; -import { ResultListDataRepresentationUserProcessInstanceFilterRepresentation } from '@alfresco/js-api'; +import { ResultListDataRepresentationUserProcessInstanceFilterRepresentation, UserFiltersApi } from '@alfresco/js-api'; @Injectable({ providedIn: 'root' }) export class ProcessFilterService { + private userFiltersApi: UserFiltersApi; + constructor(private alfrescoApiService: AlfrescoApiService) { + this.userFiltersApi = new UserFiltersApi(this.alfrescoApiService.getInstance()); } /** @@ -181,7 +184,7 @@ export class ProcessFilterService { * @returns The filter just added */ addProcessFilter(filter: FilterProcessRepresentationModel): Observable { - return from(this.alfrescoApiService.getInstance().activiti.userFiltersApi.createUserProcessInstanceFilter(filter)) + return from(this.userFiltersApi.createUserProcessInstanceFilter(filter)) .pipe( map((response: FilterProcessRepresentationModel) => { return response; @@ -197,9 +200,9 @@ export class ProcessFilterService { */ callApiProcessFilters(appId?: number): Promise { if (appId) { - return this.alfrescoApiService.getInstance().activiti.userFiltersApi.getUserProcessInstanceFilters({ appId: appId }); + return this.userFiltersApi.getUserProcessInstanceFilters({ appId: appId }); } else { - return this.alfrescoApiService.getInstance().activiti.userFiltersApi.getUserProcessInstanceFilters(); + return this.userFiltersApi.getUserProcessInstanceFilters(); } } diff --git a/lib/process-services/src/lib/process-list/services/process.service.spec.ts b/lib/process-services/src/lib/process-list/services/process.service.spec.ts index 1365751768..c4e9d2aac7 100644 --- a/lib/process-services/src/lib/process-list/services/process.service.spec.ts +++ b/lib/process-services/src/lib/process-list/services/process.service.spec.ts @@ -20,7 +20,7 @@ import { exampleProcess, mockError, fakeProcessDef, fakeTasksList } from '../../ import { ProcessFilterParamRepresentationModel } from '../models/filter-process.model'; import { ProcessInstanceVariable } from '../models/process-instance-variable.model'; import { ProcessService } from './process.service'; -import { AlfrescoApiService, setupTestBed, CoreModule } from '@alfresco/adf-core'; +import { setupTestBed, CoreModule } from '@alfresco/adf-core'; import { ProcessTestingModule } from '../../testing/process.testing.module'; declare let moment: any; @@ -28,8 +28,6 @@ declare let moment: any; describe('ProcessService', () => { let service: ProcessService; - let apiService: AlfrescoApiService; - let alfrescoApi: any; setupTestBed({ imports: [ @@ -39,9 +37,7 @@ describe('ProcessService', () => { }); beforeEach(() => { - apiService = TestBed.inject(AlfrescoApiService); - service = new ProcessService(apiService); - alfrescoApi = apiService.getInstance(); + service = TestBed.inject(ProcessService); }); describe('process instances', () => { @@ -54,9 +50,9 @@ describe('ProcessService', () => { }); beforeEach(() => { - spyOn(alfrescoApi.activiti.processApi, 'getProcessInstances') + spyOn(service['processInstancesApi'], 'getProcessInstances') .and - .returnValue(Promise.resolve({ data: [ exampleProcess ] })); + .returnValue(Promise.resolve({ data: [exampleProcess] })); }); it('should return the correct number of instances', (done) => { @@ -75,14 +71,14 @@ describe('ProcessService', () => { done(); }); }); - }); + }); describe('process instance', () => { const processId = 'test'; beforeEach(() => { - spyOn(alfrescoApi.activiti.processApi, 'getProcessInstance') + spyOn(service['processInstancesApi'], 'getProcessInstance') .and .returnValue(Promise.resolve(exampleProcess)); }); @@ -95,7 +91,7 @@ describe('ProcessService', () => { done(); }); }); - }); + }); describe('start process instance', () => { @@ -103,7 +99,7 @@ describe('ProcessService', () => { let startNewProcessInstance: jasmine.Spy; beforeEach(() => { - startNewProcessInstance = spyOn(alfrescoApi.activiti.processApi, 'startNewProcessInstance') + startNewProcessInstance = spyOn(service['processInstancesApi'], 'startNewProcessInstance') .and .returnValue(Promise.resolve(exampleProcess)); }); @@ -143,7 +139,8 @@ describe('ProcessService', () => { startNewProcessInstance = startNewProcessInstance.and.returnValue(Promise.reject(mockError)); service.startProcess(processDefId, processName).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe(mockError); done(); @@ -154,14 +151,15 @@ describe('ProcessService', () => { it('should return a default error if no data is returned by the API', (done) => { startNewProcessInstance = startNewProcessInstance.and.returnValue(Promise.reject(null)); service.startProcess(processDefId, processName).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe('Server error'); done(); } ); }); - }); + }); describe('cancel process instance', () => { @@ -169,7 +167,7 @@ describe('ProcessService', () => { let deleteProcessInstance: jasmine.Spy; beforeEach(() => { - deleteProcessInstance = spyOn(alfrescoApi.activiti.processApi, 'deleteProcessInstance') + deleteProcessInstance = spyOn(service['processInstancesApi'], 'deleteProcessInstance') .and .returnValue(Promise.resolve()); }); @@ -193,7 +191,8 @@ describe('ProcessService', () => { it('should pass on any error that is returned by the API', (done) => { deleteProcessInstance = deleteProcessInstance.and.returnValue(Promise.reject(mockError)); service.cancelProcess(null).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe(mockError); done(); @@ -204,23 +203,24 @@ describe('ProcessService', () => { it('should return a default error if no data is returned by the API', (done) => { deleteProcessInstance = deleteProcessInstance.and.returnValue(Promise.reject(null)); service.cancelProcess(null).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe('Server error'); done(); } ); }); - }); + }); describe('process definitions', () => { let getProcessDefinitions: jasmine.Spy; beforeEach(() => { - getProcessDefinitions = spyOn(alfrescoApi.activiti.processApi, 'getProcessDefinitions') + getProcessDefinitions = spyOn(service['processDefinitionsApi'], 'getProcessDefinitions') .and - .returnValue(Promise.resolve({ data: [ fakeProcessDef, fakeProcessDef ] })); + .returnValue(Promise.resolve({ data: [fakeProcessDef, fakeProcessDef] })); }); it('should return the correct number of process defs', (done) => { @@ -251,7 +251,8 @@ describe('ProcessService', () => { it('should pass on any error that is returned by the API', (done) => { getProcessDefinitions = getProcessDefinitions.and.returnValue(Promise.reject(mockError)); service.getProcessDefinitions().subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe(mockError); done(); @@ -262,14 +263,15 @@ describe('ProcessService', () => { it('should return a default error if no data is returned by the API', (done) => { getProcessDefinitions = getProcessDefinitions.and.returnValue(Promise.reject(null)); service.getProcessDefinitions().subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe('Server error'); done(); } ); }); - }); + }); describe('process instance tasks', () => { @@ -277,7 +279,7 @@ describe('ProcessService', () => { let listTasks: jasmine.Spy; beforeEach(() => { - listTasks = spyOn(alfrescoApi.activiti.taskApi, 'listTasks') + listTasks = spyOn(service['tasksApi'], 'listTasks') .and .returnValue(Promise.resolve(fakeTasksList)); }); @@ -323,7 +325,8 @@ describe('ProcessService', () => { it('should pass on any error that is returned by the API', (done) => { listTasks = listTasks.and.returnValue(Promise.reject(mockError)); service.getProcessTasks(processId).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe(mockError); done(); @@ -334,14 +337,15 @@ describe('ProcessService', () => { it('should return a default error if no data is returned by the API', (done) => { listTasks = listTasks.and.returnValue(Promise.reject(null)); service.getProcessTasks(processId).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe('Server error'); done(); } ); }); - }); + }); describe('process variables', () => { @@ -350,7 +354,7 @@ describe('ProcessService', () => { let deleteProcessInstanceVariableSpy: jasmine.Spy; beforeEach(() => { - getVariablesSpy = spyOn(alfrescoApi.activiti.processInstanceVariablesApi, 'getProcessInstanceVariables').and.returnValue(Promise.resolve([{ + getVariablesSpy = spyOn(service['processInstanceVariablesApi'], 'getProcessInstanceVariables').and.returnValue(Promise.resolve([{ name: 'var1', value: 'Test1' }, { @@ -358,10 +362,10 @@ describe('ProcessService', () => { value: 'Test3' }])); - createOrUpdateProcessInstanceVariablesSpy = spyOn(alfrescoApi.activiti.processInstanceVariablesApi, + createOrUpdateProcessInstanceVariablesSpy = spyOn(service['processInstanceVariablesApi'], 'createOrUpdateProcessInstanceVariables').and.returnValue(Promise.resolve({})); - deleteProcessInstanceVariableSpy = spyOn(alfrescoApi.activiti.processInstanceVariablesApi, + deleteProcessInstanceVariableSpy = spyOn(service['processInstanceVariablesApi'], 'deleteProcessInstanceVariable').and.returnValue(Promise.resolve()); }); @@ -375,7 +379,8 @@ describe('ProcessService', () => { it('should pass on any error that is returned by the API', (done) => { getVariablesSpy = getVariablesSpy.and.returnValue(Promise.reject(mockError)); service.getProcessInstanceVariables(null).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe(mockError); done(); @@ -386,7 +391,8 @@ describe('ProcessService', () => { it('should return a default error if no data is returned by the API', (done) => { getVariablesSpy = getVariablesSpy.and.returnValue(Promise.reject(null)); service.getProcessInstanceVariables(null).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe('Server error'); done(); @@ -412,7 +418,8 @@ describe('ProcessService', () => { it('should pass on any error that is returned by the API', (done) => { createOrUpdateProcessInstanceVariablesSpy = createOrUpdateProcessInstanceVariablesSpy.and.returnValue(Promise.reject(mockError)); service.createOrUpdateProcessInstanceVariables('123', updatedVariables).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe(mockError); done(); @@ -423,7 +430,8 @@ describe('ProcessService', () => { it('should return a default error if no data is returned by the API', (done) => { createOrUpdateProcessInstanceVariablesSpy = createOrUpdateProcessInstanceVariablesSpy.and.returnValue(Promise.reject(null)); service.createOrUpdateProcessInstanceVariables('123', updatedVariables).subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe('Server error'); done(); @@ -436,7 +444,8 @@ describe('ProcessService', () => { it('should pass on any error that is returned by the API', (done) => { deleteProcessInstanceVariableSpy = deleteProcessInstanceVariableSpy.and.returnValue(Promise.reject(mockError)); service.deleteProcessInstanceVariable('123', 'myVar').subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe(mockError); done(); @@ -447,7 +456,8 @@ describe('ProcessService', () => { it('should return a default error if no data is returned by the API', (done) => { deleteProcessInstanceVariableSpy = deleteProcessInstanceVariableSpy.and.returnValue(Promise.reject(null)); service.deleteProcessInstanceVariable('123', 'myVar').subscribe( - () => {}, + () => { + }, (res) => { expect(res).toBe('Server error'); done(); @@ -455,5 +465,5 @@ describe('ProcessService', () => { ); }); }); - }); + }); }); diff --git a/lib/process-services/src/lib/process-list/services/process.service.ts b/lib/process-services/src/lib/process-list/services/process.service.ts index 0e85a599eb..ac869a9a2b 100644 --- a/lib/process-services/src/lib/process-list/services/process.service.ts +++ b/lib/process-services/src/lib/process-list/services/process.service.ts @@ -17,7 +17,14 @@ import { AlfrescoApiService, FormValues } from '@alfresco/adf-core'; import { Injectable } from '@angular/core'; -import { RestVariable, ProcessInstanceRepresentation } from '@alfresco/js-api'; +import { + TasksApi, + ProcessDefinitionsApi, + ProcessInstancesApi, + RestVariable, + ProcessInstanceRepresentation, + ProcessInstanceVariablesApi +} from '@alfresco/js-api'; import { Observable, from, throwError, of } from 'rxjs'; import { TaskDetailsModel } from '../../task-list'; import { ProcessFilterParamRepresentationModel } from '../models/filter-process.model'; @@ -35,7 +42,16 @@ declare let moment: any; }) export class ProcessService { + private processInstanceVariablesApi: ProcessInstanceVariablesApi; + private processInstancesApi: ProcessInstancesApi; + private processDefinitionsApi: ProcessDefinitionsApi; + private tasksApi: TasksApi; + constructor(private alfrescoApiService: AlfrescoApiService) { + this.processInstanceVariablesApi = new ProcessInstanceVariablesApi(this.alfrescoApiService.getInstance()); + this.processInstancesApi = new ProcessInstancesApi(this.alfrescoApiService.getInstance()); + this.processDefinitionsApi = new ProcessDefinitionsApi(this.alfrescoApiService.getInstance()); + this.tasksApi = new TasksApi(this.alfrescoApiService.getInstance()); } /** @@ -45,7 +61,7 @@ export class ProcessService { * @returns List of process instances */ getProcessInstances(requestNode: ProcessFilterParamRepresentationModel, processDefinitionKey?: string): Observable { - return from(this.alfrescoApiService.getInstance().activiti.processApi.getProcessInstances(requestNode)) + return from(this.processInstancesApi.getProcessInstances(requestNode)) .pipe( map((res: any) => { if (processDefinitionKey) { @@ -109,7 +125,7 @@ export class ProcessService { * @returns Binary PDF data */ fetchProcessAuditPdfById(processId: string): Observable { - return from(this.alfrescoApiService.getInstance().activiti.processApi.getProcessAuditPdf(processId)) + return from(this.processInstancesApi.getProcessAuditPdf(processId)) .pipe( catchError((err) => this.handleProcessError(err)) ); @@ -121,7 +137,7 @@ export class ProcessService { * @returns JSON data */ fetchProcessAuditJsonById(processId: string): Observable { - return from(this.alfrescoApiService.getInstance().activiti.processApi.getProcessAuditJson(processId)) + return from(this.processInstancesApi.getTaskAuditLog(processId)) .pipe( catchError((err) => this.handleProcessError(err)) ); @@ -133,7 +149,7 @@ export class ProcessService { * @returns Metadata for the instance */ getProcess(processInstanceId: string): Observable { - return from(this.alfrescoApiService.getInstance().activiti.processApi.getProcessInstance(processInstanceId)) + return from(this.processInstancesApi.getProcessInstance(processInstanceId)) .pipe( catchError((err) => this.handleProcessError(err)) ); @@ -150,9 +166,9 @@ export class ProcessService { processInstanceId: processInstanceId, state: state } : { - processInstanceId: processInstanceId - }; - return from(this.alfrescoApiService.getInstance().activiti.taskApi.listTasks(taskOpts)) + processInstanceId: processInstanceId + }; + return from(this.tasksApi.listTasks(taskOpts)) .pipe( map(this.extractData), map((tasks) => tasks.map((task: any) => { @@ -173,10 +189,10 @@ export class ProcessService { latest: true, appDefinitionId: appId } : { - latest: true - }; + latest: true + }; return from( - this.alfrescoApiService.getInstance().activiti.processApi.getProcessDefinitions(opts) + this.processDefinitionsApi.getProcessDefinitions(opts) ) .pipe( map(this.extractData), @@ -209,7 +225,7 @@ export class ProcessService { startRequest.variables = variables; } return from( - this.alfrescoApiService.getInstance().activiti.processApi.startNewProcessInstance(startRequest) + this.processInstancesApi.startNewProcessInstance(startRequest) ) .pipe( map((pd) => new ProcessInstance(pd)), @@ -224,7 +240,7 @@ export class ProcessService { */ cancelProcess(processInstanceId: string): Observable { return from( - this.alfrescoApiService.getInstance().activiti.processApi.deleteProcessInstance(processInstanceId) + this.processInstancesApi.deleteProcessInstance(processInstanceId) ) .pipe( catchError((err) => this.handleProcessError(err)) @@ -238,7 +254,7 @@ export class ProcessService { */ getProcessInstanceVariables(processInstanceId: string): Observable { return from( - this.alfrescoApiService.getInstance().activiti.processInstanceVariablesApi.getProcessInstanceVariables(processInstanceId) + this.processInstanceVariablesApi.getProcessInstanceVariables(processInstanceId) ) .pipe( map((processVars: any[]) => processVars.map((currentProcessVar) => new ProcessInstanceVariable(currentProcessVar))), @@ -254,10 +270,10 @@ export class ProcessService { */ createOrUpdateProcessInstanceVariables(processInstanceId: string, variables: RestVariable[]): Observable { return from( - this.alfrescoApiService.getInstance().activiti.processInstanceVariablesApi.createOrUpdateProcessInstanceVariables(processInstanceId, variables) + this.processInstanceVariablesApi.createOrUpdateProcessInstanceVariables(processInstanceId, variables) ).pipe( - catchError((err) => this.handleProcessError(err)) - ); + catchError((err) => this.handleProcessError(err)) + ); } /** @@ -268,7 +284,7 @@ export class ProcessService { */ deleteProcessInstanceVariable(processInstanceId: string, variableName: string): Observable { return from( - this.alfrescoApiService.getInstance().activiti.processInstanceVariablesApi.deleteProcessInstanceVariable(processInstanceId, variableName) + this.processInstanceVariablesApi.deleteProcessInstanceVariable(processInstanceId, variableName) ) .pipe( catchError((err) => this.handleProcessError(err)) diff --git a/lib/process-services/src/lib/task-list/services/process-upload.service.ts b/lib/process-services/src/lib/task-list/services/process-upload.service.ts index 578da6a2c9..c6de92e6eb 100644 --- a/lib/process-services/src/lib/task-list/services/process-upload.service.ts +++ b/lib/process-services/src/lib/task-list/services/process-upload.service.ts @@ -16,6 +16,7 @@ */ import { AlfrescoApiService, AppConfigService, DiscoveryApiService, UploadService } from '@alfresco/adf-core'; +import { ActivitiContentApi } from '@alfresco/js-api'; import { Injectable } from '@angular/core'; import { throwError } from 'rxjs'; @@ -24,8 +25,11 @@ import { throwError } from 'rxjs'; }) export class ProcessUploadService extends UploadService { + contentApi: ActivitiContentApi; + constructor(protected apiService: AlfrescoApiService, appConfigService: AppConfigService, discoveryApiService: DiscoveryApiService) { super(apiService, appConfigService, discoveryApiService); + this.contentApi = new ActivitiContentApi(apiService.getInstance()); } getUploadPromise(file: any): any { @@ -33,7 +37,7 @@ export class ProcessUploadService extends UploadService { isRelatedContent: true }; const processInstanceId = file.options.parentId; - const promise = this.apiService.getInstance().activiti.contentApi.createRelatedContentOnProcessInstance(processInstanceId, file.file, opts); + const promise = this.contentApi.createRelatedContentOnProcessInstance(processInstanceId, file.file, opts); promise.catch((err) => this.handleError(err)); diff --git a/lib/process-services/src/lib/task-list/services/task-filter.service.ts b/lib/process-services/src/lib/task-list/services/task-filter.service.ts index 7ece826ac8..ff5090b305 100644 --- a/lib/process-services/src/lib/task-list/services/task-filter.service.ts +++ b/lib/process-services/src/lib/task-list/services/task-filter.service.ts @@ -20,14 +20,18 @@ import { Injectable } from '@angular/core'; import { Observable, forkJoin, from, throwError } from 'rxjs'; import { FilterRepresentationModel } from '../models/filter.model'; import { map, catchError } from 'rxjs/operators'; +import { UserFiltersApi } from '@alfresco/js-api'; @Injectable({ providedIn: 'root' }) export class TaskFilterService { + private userFiltersApi: UserFiltersApi; + constructor(private apiService: AlfrescoApiService, private logService: LogService) { + this.userFiltersApi = new UserFiltersApi(this.apiService.getInstance()); } /** @@ -60,13 +64,29 @@ export class TaskFilterService { const filters: FilterRepresentationModel[] = []; res.forEach((filter) => { if (filter.name === involvedTasksFilter.name) { - filters.push(new FilterRepresentationModel({ ...filter, filter: involvedTasksFilter.filter, appId })); + filters.push(new FilterRepresentationModel({ + ...filter, + filter: involvedTasksFilter.filter, + appId + })); } else if (filter.name === myTasksFilter.name) { - filters.push(new FilterRepresentationModel({ ...filter, filter: myTasksFilter.filter, appId })); + filters.push(new FilterRepresentationModel({ + ...filter, + filter: myTasksFilter.filter, + appId + })); } else if (filter.name === queuedTasksFilter.name) { - filters.push(new FilterRepresentationModel({ ...filter, filter: queuedTasksFilter.filter, appId })); + filters.push(new FilterRepresentationModel({ + ...filter, + filter: queuedTasksFilter.filter, + appId + })); } else if (filter.name === completedTasksFilter.name) { - filters.push(new FilterRepresentationModel({ ...filter, filter: completedTasksFilter.filter, appId })); + filters.push(new FilterRepresentationModel({ + ...filter, + filter: completedTasksFilter.filter, + appId + })); } }); observer.next(filters); @@ -130,7 +150,7 @@ export class TaskFilterService { * @returns Details of task filter just added */ addFilter(filter: FilterRepresentationModel): Observable { - return from(this.apiService.getInstance().activiti.userFiltersApi.createUserTaskFilter(filter)) + return from(this.userFiltersApi.createUserTaskFilter(filter)) .pipe( map((response: FilterRepresentationModel) => { return response; @@ -146,9 +166,9 @@ export class TaskFilterService { */ callApiTaskFilters(appId?: number): Promise { if (appId) { - return this.apiService.getInstance().activiti.userFiltersApi.getUserTaskFilters({appId: appId}); + return this.userFiltersApi.getUserTaskFilters({ appId: appId }); } else { - return this.apiService.getInstance().activiti.userFiltersApi.getUserTaskFilters(); + return this.userFiltersApi.getUserTaskFilters(); } } @@ -164,7 +184,7 @@ export class TaskFilterService { 'appId': appId, 'recent': false, 'icon': 'glyphicon-inbox', - 'filter': {'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'assignee'}, + 'filter': { 'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'assignee' }, index }); } @@ -181,7 +201,7 @@ export class TaskFilterService { 'appId': appId, 'recent': false, 'icon': 'glyphicon-align-left', - 'filter': {'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'involved'}, + 'filter': { 'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'involved' }, index }); } @@ -198,7 +218,7 @@ export class TaskFilterService { 'appId': appId, 'recent': false, 'icon': 'glyphicon-record', - 'filter': {'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'candidate'}, + 'filter': { 'sort': 'created-desc', 'name': '', 'state': 'open', 'assignment': 'candidate' }, index }); } @@ -215,7 +235,7 @@ export class TaskFilterService { 'appId': appId, 'recent': true, 'icon': 'glyphicon-ok-sign', - 'filter': {'sort': 'created-desc', 'name': '', 'state': 'completed', 'assignment': 'involved'}, + 'filter': { 'sort': 'created-desc', 'name': '', 'state': 'completed', 'assignment': 'involved' }, index }); } diff --git a/lib/process-services/src/lib/task-list/services/task-upload.service.ts b/lib/process-services/src/lib/task-list/services/task-upload.service.ts index 5475875f58..525da9236c 100644 --- a/lib/process-services/src/lib/task-list/services/task-upload.service.ts +++ b/lib/process-services/src/lib/task-list/services/task-upload.service.ts @@ -18,14 +18,18 @@ import { AlfrescoApiService, AppConfigService, DiscoveryApiService, UploadService } from '@alfresco/adf-core'; import { Injectable } from '@angular/core'; import { throwError } from 'rxjs'; +import { ActivitiContentApi } from '@alfresco/js-api'; @Injectable({ providedIn: 'root' }) export class TaskUploadService extends UploadService { + private contentApi: ActivitiContentApi; + constructor(protected apiService: AlfrescoApiService, appConfigService: AppConfigService, discoveryApiService: DiscoveryApiService) { super(apiService, appConfigService, discoveryApiService); + this.contentApi = new ActivitiContentApi(apiService.getInstance()); } getUploadPromise(file: any): any { @@ -33,7 +37,7 @@ export class TaskUploadService extends UploadService { isRelatedContent: true }; const taskId = file.options.parentId; - const promise = this.apiService.getInstance().activiti.contentApi.createRelatedContentOnTask(taskId, file.file, opts); + const promise = this.contentApi.createRelatedContentOnTask(taskId, file.file, opts); promise.catch((err) => this.handleError(err)); diff --git a/lib/process-services/src/lib/task-list/services/tasklist.service.ts b/lib/process-services/src/lib/task-list/services/tasklist.service.ts index d0c51908ad..03fe3ef0b2 100644 --- a/lib/process-services/src/lib/task-list/services/tasklist.service.ts +++ b/lib/process-services/src/lib/task-list/services/tasklist.service.ts @@ -24,9 +24,9 @@ import { Form } from '../models/form.model'; import { TaskDetailsModel } from '../models/task-details.model'; import { TaskListModel } from '../models/task-list.model'; import { - TaskQueryRepresentation, - AssigneeIdentifierRepresentation, - TaskUpdateRepresentation + TaskQueryRepresentation, AssigneeIdentifierRepresentation, + TaskUpdateRepresentation, ModelsApi, TaskActionsApi, TasksApi, + ChecklistsApi } from '@alfresco/js-api'; @Injectable({ @@ -34,8 +34,17 @@ import { }) export class TaskListService { + private modelsApi: ModelsApi; + private tasksApi: TasksApi; + private taskActionsApi: TaskActionsApi; + private checklistsApi: ChecklistsApi; + constructor(private apiService: AlfrescoApiService, private logService: LogService) { + this.modelsApi = new ModelsApi(this.apiService.getInstance()); + this.taskActionsApi = new TaskActionsApi(this.apiService.getInstance()); + this.tasksApi = new TasksApi(this.apiService.getInstance()); + this.checklistsApi = new ChecklistsApi(this.apiService.getInstance()); } /** @@ -192,7 +201,7 @@ export class TaskListService { 'modelType': 2 // Integer | modelType }; - return from(this.apiService.getInstance().activiti.modelsApi.getModels(opts)) + return from(this.modelsApi.getModels(opts)) .pipe( map(response => { const forms: Form[] = []; @@ -212,7 +221,7 @@ export class TaskListService { * @returns Null response notifying when the operation is complete */ attachFormToATask(taskId: string, formId: number): Observable { - return from(this.apiService.taskApi.attachForm(taskId, { 'formId': formId })) + return from(this.taskActionsApi.attachForm(taskId, { 'formId': formId })) .pipe( catchError((err) => this.handleError(err)) ); @@ -263,7 +272,7 @@ export class TaskListService { * @returns Null response notifying when the operation is complete */ completeTask(taskId: string) { - return from(this.apiService.taskApi.completeTask(taskId)) + return from(this.taskActionsApi.completeTask(taskId)) .pipe( catchError((err) => this.handleError(err)) ); @@ -337,7 +346,7 @@ export class TaskListService { * @returns Details of the claimed task */ claimTask(taskId: string): Observable { - return from(this.apiService.taskApi.claimTask(taskId)) + return from(this.taskActionsApi.claimTask(taskId)) .pipe( catchError((err) => this.handleError(err)) ); @@ -349,7 +358,7 @@ export class TaskListService { * @returns Null response notifying when the operation is complete */ unclaimTask(taskId: string): Observable { - return from(this.apiService.taskApi.unclaimTask(taskId)) + return from(this.taskActionsApi.unclaimTask(taskId)) .pipe( catchError((err) => this.handleError(err)) ); @@ -362,7 +371,7 @@ export class TaskListService { * @returns Updated task details */ updateTask(taskId: string, updated: TaskUpdateRepresentation): Observable { - return from(this.apiService.taskApi.updateTask(taskId, updated)) + return from(this.tasksApi.updateTask(taskId, updated)) .pipe( map((result) => result), catchError((err) => this.handleError(err)) @@ -375,7 +384,7 @@ export class TaskListService { * @returns Binary PDF data */ fetchTaskAuditPdfById(taskId: string): Observable { - return from(this.apiService.taskApi.getTaskAuditPdf(taskId)) + return from(this.tasksApi.getTaskAuditPdf(taskId)) .pipe( map((data) => data), catchError((err) => this.handleError(err)) @@ -388,42 +397,42 @@ export class TaskListService { * @returns JSON data */ fetchTaskAuditJsonById(taskId: string): Observable { - return from(this.apiService.taskApi.getTaskAuditJson(taskId)) + return from(this.tasksApi.getTaskAuditLog(taskId)) .pipe( catchError((err) => this.handleError(err)) ); } private callApiTasksFiltered(requestNode: TaskQueryRepresentation): Promise { - return this.apiService.taskApi.listTasks(requestNode); + return this.tasksApi.listTasks(requestNode); } private callApiTaskDetails(taskId: string): Promise { - return this.apiService.taskApi.getTask(taskId); + return this.tasksApi.getTask(taskId); } private callApiAddTask(task: TaskDetailsModel): Promise { - return this.apiService.taskApi.addSubtask(task.parentTaskId, task); + return this.checklistsApi.addSubtask(task.parentTaskId, task); } private callApiDeleteTask(taskId: string): Promise { - return this.apiService.taskApi.deleteTask(taskId); + return this.tasksApi.deleteTask(taskId); } private callApiDeleteForm(taskId: string): Promise { - return this.apiService.taskApi.removeForm(taskId); + return this.taskActionsApi.removeForm(taskId); } private callApiTaskChecklist(taskId: string): Promise { - return this.apiService.taskApi.getChecklist(taskId); + return this.checklistsApi.getChecklist(taskId); } private callApiCreateTask(task: TaskDetailsModel): Promise { - return this.apiService.taskApi.createNewTask(task); + return this.tasksApi.createNewTask(task); } private callApiAssignTask(taskId: string, requestNode: AssigneeIdentifierRepresentation): Promise { - return this.apiService.taskApi.assignTask(taskId, requestNode); + return this.taskActionsApi.assignTask(taskId, requestNode); } private handleError(error: any) { diff --git a/scripts/lint.sh b/scripts/lint.sh index 06fa8e8736..676abcad09 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -12,11 +12,11 @@ echo "Lint" nx affected:lint --parallel --all --maxParallel=9 || exit 1 echo "Style Lint" -npm run stylelint || exit 1 +npm run stylelint || exit 1 echo "Spell check" -npm run spellcheck || exit 1 +npm run spellcheck || exit 1 echo "License check" -npm run license-checker || exit 1 -npm run validate-config || exit 1 +npm run license-checker || exit 1 +npm run validate-config || exit 1