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

* remove compatibility step 1

* remove compatibility step 2

* remove compatibility step 3

* remove compatibility step 4

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

View File

@@ -1,199 +0,0 @@
/*!
* @license
* Copyright 2019 Alfresco Software, Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AspectEntry, AspectPaging } from '@alfresco/js-api';
import { TestBed } from '@angular/core/testing';
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
import { TranslateModule } from '@ngx-translate/core';
import { AlfrescoApiService, AppConfigService, LogService, setupTestBed } from 'core';
import { of, Subject, throwError } from 'rxjs';
import { ContentTestingModule } from '../testing/content.testing.module';
import { AspectListService } from './aspect-list.service';
const aspectListMock: AspectEntry[] = [{
entry: {
parentId: 'frs:aspectZero',
id: 'frs:AspectOne',
description: 'First Aspect with random description',
title: 'FirstAspect',
properties: [
{
id: 'channelPassword',
title: 'The authenticated channel password',
dataType: 'd:propA'
},
{
id: 'channelUsername',
title: 'The authenticated channel username',
dataType: 'd:propB'
}
]
}
},
{
entry: {
parentId: 'frs:AspectZer',
id: 'frs:SecondAspect',
description: 'Second Aspect description',
title: 'SecondAspect',
properties: [
{
id: 'assetId',
title: 'Published Asset Id',
dataType: 'd:text'
},
{
id: 'assetUrl',
title: 'Published Asset URL',
dataType: 'd:text'
}
]
}
}];
const customAspectListMock: AspectEntry[] = [{
entry: {
parentId: 'frs:aspectZero',
id: 'frs:AspectCustom',
description: 'First Aspect with random description',
title: 'FirstAspect',
properties: [
{
id: 'channelPassword',
title: 'The authenticated channel password',
dataType: 'd:propA'
},
{
id: 'channelUsername',
title: 'The authenticated channel username',
dataType: 'd:propB'
}
]
}
}];
const listAspectResp: AspectPaging = {
list : {
entries: aspectListMock
}
};
const customListAspectResp: AspectPaging = {
list : {
entries: customAspectListMock
}
};
describe('AspectListService', () => {
describe('should open the dialog', () => {
let service: AspectListService;
let materialDialog: MatDialog;
let spyOnDialogOpen: jasmine.Spy;
let spyOnDialogClose: jasmine.Spy;
const afterOpenObservable: Subject<any> = new Subject();
setupTestBed({
imports: [
TranslateModule.forRoot(),
ContentTestingModule,
MatDialogModule
]
});
beforeEach(() => {
service = TestBed.inject(AspectListService);
materialDialog = TestBed.inject(MatDialog);
spyOnDialogOpen = spyOn(materialDialog, 'open').and.returnValue({
afterOpen: () => afterOpenObservable,
afterClosed: () => of({}),
componentInstance: {
error: new Subject<any>()
}
} as any);
spyOnDialogClose = spyOn(materialDialog, 'closeAll');
});
it('should open the aspect list dialog', () => {
service.openAspectListDialog();
expect(spyOnDialogOpen).toHaveBeenCalled();
});
it('should close the dialog', () => {
service.close();
expect(spyOnDialogClose).toHaveBeenCalled();
});
});
describe('should fetch the list of the aspects', () => {
let service: AspectListService;
let appConfigService: AppConfigService;
let apiService: AlfrescoApiService;
let logService: LogService;
let aspectTypesApi: any;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ContentTestingModule]
});
aspectTypesApi = jasmine.createSpyObj('AspectsApi', ['listAspects']);
appConfigService = TestBed.inject(AppConfigService);
apiService = TestBed.inject(AlfrescoApiService);
logService = TestBed.inject(LogService);
spyOn(appConfigService, 'get').and.returnValue({ 'default': ['frs:AspectOne'] });
spyOnProperty(apiService, 'aspectsApi').and.returnValue(aspectTypesApi);
service = TestBed.inject(AspectListService);
});
it('should get the list of only available aspects', (done) => {
aspectTypesApi.listAspects.and.returnValues(of(listAspectResp), of(customListAspectResp));
service.getAspects().subscribe((list) => {
expect(list.length).toBe(2);
expect(list[0].entry.id).toBe('frs:AspectOne');
expect(list[1].entry.id).toBe('frs:AspectCustom');
done();
});
});
it('should return a value when the standard aspect call fails', (done) => {
spyOn(logService, 'error').and.stub();
aspectTypesApi.listAspects.and.returnValues(throwError('Insert Coin'), of(customListAspectResp));
service.getAspects().subscribe((list) => {
expect(list.length).toBe(1);
expect(list[0].entry.id).toBe('frs:AspectCustom');
expect(logService.error).toHaveBeenCalled();
done();
});
});
it('should return a value when the custom aspect call fails', (done) => {
spyOn(logService, 'error').and.stub();
aspectTypesApi.listAspects.and.returnValues(of(listAspectResp), throwError('Insert Coin'));
service.getAspects().subscribe((list) => {
expect(list.length).toBe(1);
expect(list[0].entry.id).toBe('frs:AspectOne');
expect(logService.error).toHaveBeenCalled();
done();
});
});
});
});

View File

@@ -22,17 +22,20 @@ import { from, Observable, of, Subject, zip } from 'rxjs';
import { AspectListDialogComponentData } from './aspect-list-dialog-data.interface';
import { AspectListDialogComponent } from './aspect-list-dialog.component';
import { catchError, map } from 'rxjs/operators';
import { AspectEntry, AspectPaging } from '@alfresco/js-api';
import { AspectEntry, AspectPaging, AspectsApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
})
export class AspectListService {
private aspectsApi: AspectsApi;
constructor(private alfrescoApiService: AlfrescoApiService,
private appConfigService: AppConfigService,
private dialog: MatDialog,
private logService: LogService) {
this.aspectsApi = new AspectsApi(this.alfrescoApiService.getInstance());
}
getAspects(): Observable<AspectEntry[]> {
@@ -50,7 +53,7 @@ export class AspectListService {
where,
include: ['properties']
};
return from(this.alfrescoApiService.aspectsApi.listAspects(opts))
return from(this.aspectsApi.listAspects(opts))
.pipe(
map((result: AspectPaging) => this.filterAspectByConfig(whiteList, result?.list?.entries)),
catchError((error) => {
@@ -66,7 +69,7 @@ export class AspectListService {
where,
include: ['properties']
};
return from(this.alfrescoApiService.aspectsApi.listAspects(opts))
return from(this.aspectsApi.listAspects(opts))
.pipe(
map((result: AspectPaging) => result?.list?.entries),
catchError((error) => {

View File

@@ -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);
});

View File

@@ -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', () => {

View File

@@ -20,18 +20,22 @@ import { AlfrescoApiService } from '@alfresco/adf-core';
import { Observable, defer, forkJoin } from 'rxjs';
import { PropertyGroup, PropertyGroupContainer } from '../interfaces/content-metadata.interfaces';
import { map } from 'rxjs/operators';
import { ClassesApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
})
export class PropertyDescriptorsService {
private classesApi: ClassesApi;
constructor(private alfrescoApiService: AlfrescoApiService) {}
constructor(private alfrescoApiService: AlfrescoApiService) {
this.classesApi = new ClassesApi(this.alfrescoApiService.getInstance());
}
load(groupNames: string[]): Observable<PropertyGroupContainer> {
const groupFetchStreams = groupNames
.map((groupName) => groupName.replace(':', '_'))
.map((groupName) => defer( () => this.alfrescoApiService.classesApi.getClass(groupName)) );
.map((groupName) => defer(() => this.classesApi.getClass(groupName)));
return forkJoin(groupFetchStreams).pipe(
map(this.convertToObject)

View File

@@ -17,7 +17,7 @@
import { Directive, Input, HostListener, OnChanges, NgZone, OnDestroy } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { NodeEntry, Node } from '@alfresco/js-api';
import { NodeEntry, NodesApi } from '@alfresco/js-api';
import { ShareDialogComponent } from './content-node-share.dialog';
import { Observable, from, Subject } from 'rxjs';
@@ -43,11 +43,13 @@ export class NodeSharedDirective implements OnChanges, OnDestroy {
baseShareUrl: string;
private onDestroy$ = new Subject<boolean>();
private nodesApi = new NodesApi();
constructor(
private dialog: MatDialog,
private zone: NgZone,
private alfrescoApiService: AlfrescoApiService) {
this.nodesApi = new NodesApi(this.alfrescoApiService.getInstance());
}
ngOnDestroy() {
@@ -61,8 +63,8 @@ export class NodeSharedDirective implements OnChanges, OnDestroy {
const nodeId = nodeEntry.entry['nodeId'] || nodeEntry.entry['guid'];
if (nodeId) {
this.getNodeInfo(nodeId).subscribe((entry) => {
this.openShareLinkDialog({ entry });
this.getNodeInfo(nodeId).subscribe((node) => {
this.openShareLinkDialog(node);
});
} else {
this.openShareLinkDialog(nodeEntry);
@@ -70,13 +72,13 @@ export class NodeSharedDirective implements OnChanges, OnDestroy {
}
}
private getNodeInfo(nodeId: string): Observable<Node> {
private getNodeInfo(nodeId: string): Observable<NodeEntry> {
const options = {
include: ['allowableOperations']
include: ['allowableOperations']
};
return from(this.alfrescoApiService.nodesApi.getNodeInfo(nodeId, options));
}
return from(this.nodesApi.getNode(nodeId, options));
}
private openShareLinkDialog(node: NodeEntry) {
this.dialog.open(ShareDialogComponent, {

View File

@@ -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();
});
});
});

View File

@@ -15,7 +15,7 @@
* limitations under the License.
*/
import { TypeEntry, TypePaging } from '@alfresco/js-api';
import { TypeEntry, TypePaging, TypesApi } from '@alfresco/js-api';
import { Injectable } from '@angular/core';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { from, Observable } from 'rxjs';
@@ -25,11 +25,14 @@ import { map } from 'rxjs/operators';
})
export class ContentTypeService {
private typesApi: TypesApi;
constructor(private alfrescoApiService: AlfrescoApiService) {
this.typesApi = new TypesApi(this.alfrescoApiService.getInstance());
}
getContentTypeByPrefix(prefixedType: string): Observable<TypeEntry> {
return from(this.alfrescoApiService.typesApi.getType(prefixedType));
return from(this.typesApi.getType(prefixedType));
}
getContentTypeChildren(nodeType: string): Observable<TypeEntry[]> {
@@ -38,7 +41,7 @@ export class ContentTypeService {
where,
include: ['properties']
};
return from(this.alfrescoApiService.typesApi.listTypes(opts)).pipe(
return from(this.typesApi.listTypes(opts)).pipe(
map((result: TypePaging) => result.list.entries)
);
}

View File

@@ -19,7 +19,7 @@ import { LibraryDialogComponent } from './library.dialog';
import { TestBed, fakeAsync, tick, flush, ComponentFixture, flushMicrotasks } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { MatDialogRef } from '@angular/material/dialog';
import { AlfrescoApiService, setupTestBed, SitesService } from '@alfresco/adf-core';
import { setupTestBed, SitesService } from '@alfresco/adf-core';
import { ContentTestingModule } from '../../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
import { of, throwError } from 'rxjs';
@@ -30,7 +30,6 @@ describe('LibraryDialogComponent', () => {
let fixture: ComponentFixture<LibraryDialogComponent>;
let component: LibraryDialogComponent;
let sitesService: SitesService;
let alfrescoApi;
let findSitesSpy;
const findSitesResponse = { list: { entries: [] } };
const dialogRef = {
@@ -51,9 +50,8 @@ describe('LibraryDialogComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(LibraryDialogComponent);
component = fixture.componentInstance;
alfrescoApi = TestBed.inject(AlfrescoApiService);
sitesService = TestBed.inject(SitesService);
findSitesSpy = spyOn(alfrescoApi.getInstance().core.queriesApi, 'findSites');
findSitesSpy = spyOn(component['queriesApi'], 'findSites');
});
afterEach(() => {

View File

@@ -17,265 +17,267 @@
import { Observable, Subject } from 'rxjs';
import {
Component,
OnInit,
Output,
EventEmitter,
OnDestroy,
ViewEncapsulation
Component,
OnInit,
Output,
EventEmitter,
OnDestroy,
ViewEncapsulation
} from '@angular/core';
import {
FormBuilder,
FormGroup,
Validators,
FormControl,
AbstractControl
FormBuilder,
FormGroup,
Validators,
FormControl,
AbstractControl
} from '@angular/forms';
import { MatDialogRef } from '@angular/material/dialog';
import { SiteBodyCreate, SiteEntry, SitePaging } from '@alfresco/js-api';
import { QueriesApi, SiteBodyCreate, SiteEntry, SitePaging } from '@alfresco/js-api';
import { AlfrescoApiService, SitesService } from '@alfresco/adf-core';
import { debounceTime, finalize, mergeMap, takeUntil } from 'rxjs/operators';
@Component({
selector: 'adf-library-dialog',
styleUrls: ['./library.dialog.scss'],
templateUrl: './library.dialog.html',
encapsulation: ViewEncapsulation.None,
host: { class: 'adf-library-dialog' }
selector: 'adf-library-dialog',
styleUrls: ['./library.dialog.scss'],
templateUrl: './library.dialog.html',
encapsulation: ViewEncapsulation.None,
host: { class: 'adf-library-dialog' }
})
export class LibraryDialogComponent implements OnInit, OnDestroy {
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when an error occurs. */
@Output()
error: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when the new library is created successfully. The
* event parameter is a SiteEntry object with the details of the
* newly-created library.
*/
@Output()
success: EventEmitter<any> = new EventEmitter<any>();
/** Emitted when the new library is created successfully. The
* event parameter is a SiteEntry object with the details of the
* newly-created library.
*/
@Output()
success: EventEmitter<any> = new EventEmitter<any>();
onDestroy$: Subject<boolean> = new Subject<boolean>();
onDestroy$: Subject<boolean> = new Subject<boolean>();
createTitle = 'LIBRARY.DIALOG.CREATE_TITLE';
libraryTitleExists = false;
form: FormGroup;
visibilityOption: any;
visibilityOptions = [
{ value: 'PUBLIC', label: 'LIBRARY.VISIBILITY.PUBLIC', disabled: false },
{ value: 'PRIVATE', label: 'LIBRARY.VISIBILITY.PRIVATE', disabled: false },
{
value: 'MODERATED',
label: 'LIBRARY.VISIBILITY.MODERATED',
disabled: false
}
];
disableCreateButton = false;
constructor(
private alfrescoApiService: AlfrescoApiService,
private sitesService: SitesService,
private formBuilder: FormBuilder,
private dialog: MatDialogRef<LibraryDialogComponent>
) {}
ngOnInit() {
const validators = {
id: [
Validators.required,
Validators.maxLength(72),
this.forbidSpecialCharacters
],
title: [
Validators.required,
this.forbidOnlySpaces,
Validators.minLength(2),
Validators.maxLength(256)
],
description: [Validators.maxLength(512)]
};
this.form = this.formBuilder.group({
title: [null, validators.title],
id: [null, validators.id, this.createSiteIdValidator()],
description: ['', validators.description]
});
this.visibilityOption = this.visibilityOptions[0].value;
this.form.controls['title'].valueChanges
.pipe(
debounceTime(500),
mergeMap(
(title) => this.checkLibraryNameExists(title),
(title) => title
),
takeUntil(this.onDestroy$)
)
.subscribe((title: string) => {
if (!this.form.controls['id'].dirty && this.canGenerateId(title)) {
this.form.patchValue({ id: this.sanitize(title.trim()) });
this.form.controls['id'].markAsTouched();
createTitle = 'LIBRARY.DIALOG.CREATE_TITLE';
libraryTitleExists = false;
form: FormGroup;
visibilityOption: any;
visibilityOptions = [
{ value: 'PUBLIC', label: 'LIBRARY.VISIBILITY.PUBLIC', disabled: false },
{ value: 'PRIVATE', label: 'LIBRARY.VISIBILITY.PRIVATE', disabled: false },
{
value: 'MODERATED',
label: 'LIBRARY.VISIBILITY.MODERATED',
disabled: false
}
});
}
];
disableCreateButton = false;
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
queriesApi: QueriesApi;
get title(): string {
const { title } = this.form.value;
return (title || '').trim();
}
get id(): string {
const { id } = this.form.value;
return (id || '').trim();
}
get description(): string {
const { description } = this.form.value;
return (description || '').trim();
}
get visibility(): string {
return this.visibilityOption || '';
}
submit() {
const { form, dialog } = this;
if (!form.valid) {
return;
constructor(
private alfrescoApiService: AlfrescoApiService,
private sitesService: SitesService,
private formBuilder: FormBuilder,
private dialog: MatDialogRef<LibraryDialogComponent>
) {
this.queriesApi = new QueriesApi(this.alfrescoApiService.getInstance());
}
this.disableCreateButton = true;
this.create().pipe(finalize(() => this.disableCreateButton = false)).subscribe(
(node: SiteEntry) => {
this.success.emit(node);
dialog.close(node);
},
(error) => this.handleError(error)
);
}
visibilityChangeHandler(event) {
this.visibilityOption = event.value;
}
private create(): Observable<SiteEntry> {
const { title, id, description, visibility } = this;
const siteBody = <SiteBodyCreate> {
id,
title,
description,
visibility
};
return this.sitesService.createSite(siteBody);
}
private sanitize(input: string) {
return input.replace(/[\s\s]+/g, '-').replace(/[^A-Za-z0-9-]/g, '');
}
private canGenerateId(title) {
return Boolean(title.replace(/[^A-Za-z0-9-]/g, '').length);
}
private handleError(error: any): any {
try {
const {
error: { statusCode }
} = JSON.parse(error.message);
if (statusCode === 409) {
this.form.controls['id'].setErrors({
message: 'LIBRARY.ERRORS.CONFLICT'
});
}
} catch (error) {
}
return error;
}
private async checkLibraryNameExists(libraryTitle: string) {
let entries = [];
try {
entries = (await this.findLibraryByTitle(libraryTitle)).list.entries;
} catch {
entries = [];
}
if (entries.length) {
this.libraryTitleExists = entries[0].entry.title.toLowerCase() === libraryTitle.toLowerCase();
} else {
this.libraryTitleExists = false;
}
}
private findLibraryByTitle(libraryTitle: string): Promise<SitePaging> {
return this.alfrescoApiService
.getInstance()
.core.queriesApi.findSites(libraryTitle, {
maxItems: 1,
fields: ['title']
});
}
private forbidSpecialCharacters({ value }: FormControl) {
if (value === null || value.length === 0) {
return null;
}
const validCharacters: RegExp = /[^A-Za-z0-9-]/;
const isValid: boolean = !validCharacters.test(value);
return isValid
? null
: {
message: 'LIBRARY.ERRORS.ILLEGAL_CHARACTERS'
ngOnInit() {
const validators = {
id: [
Validators.required,
Validators.maxLength(72),
this.forbidSpecialCharacters
],
title: [
Validators.required,
this.forbidOnlySpaces,
Validators.minLength(2),
Validators.maxLength(256)
],
description: [Validators.maxLength(512)]
};
}
private forbidOnlySpaces({ value }: FormControl) {
if (value === null || value.length === 0) {
return null;
this.form = this.formBuilder.group({
title: [null, validators.title],
id: [null, validators.id, this.createSiteIdValidator()],
description: ['', validators.description]
});
this.visibilityOption = this.visibilityOptions[0].value;
this.form.controls['title'].valueChanges
.pipe(
debounceTime(500),
mergeMap(
(title) => this.checkLibraryNameExists(title),
(title) => title
),
takeUntil(this.onDestroy$)
)
.subscribe((title: string) => {
if (!this.form.controls['id'].dirty && this.canGenerateId(title)) {
this.form.patchValue({ id: this.sanitize(title.trim()) });
this.form.controls['id'].markAsTouched();
}
});
}
const isValid: boolean = !!(value || '').trim();
ngOnDestroy() {
this.onDestroy$.next(true);
this.onDestroy$.complete();
}
return isValid
? null
: {
message: 'LIBRARY.ERRORS.ONLY_SPACES'
get title(): string {
const { title } = this.form.value;
return (title || '').trim();
}
get id(): string {
const { id } = this.form.value;
return (id || '').trim();
}
get description(): string {
const { description } = this.form.value;
return (description || '').trim();
}
get visibility(): string {
return this.visibilityOption || '';
}
submit() {
const { form, dialog } = this;
if (!form.valid) {
return;
}
this.disableCreateButton = true;
this.create().pipe(finalize(() => this.disableCreateButton = false)).subscribe(
(node: SiteEntry) => {
this.success.emit(node);
dialog.close(node);
},
(error) => this.handleError(error)
);
}
visibilityChangeHandler(event) {
this.visibilityOption = event.value;
}
private create(): Observable<SiteEntry> {
const { title, id, description, visibility } = this;
const siteBody = <SiteBodyCreate> {
id,
title,
description,
visibility
};
}
private createSiteIdValidator() {
let timer;
return this.sitesService.createSite(siteBody);
}
return (control: AbstractControl) => {
if (timer) {
clearTimeout(timer);
}
private sanitize(input: string) {
return input.replace(/[\s\s]+/g, '-').replace(/[^A-Za-z0-9-]/g, '');
}
return new Promise((resolve) => {
timer = setTimeout(() => {
return this.sitesService.getSite(control.value).subscribe(
() => resolve({ message: 'LIBRARY.ERRORS.EXISTENT_SITE' }),
() => resolve(null)
);
}, 300);
});
};
}
private canGenerateId(title) {
return Boolean(title.replace(/[^A-Za-z0-9-]/g, '').length);
}
private handleError(error: any): any {
try {
const {
error: { statusCode }
} = JSON.parse(error.message);
if (statusCode === 409) {
this.form.controls['id'].setErrors({
message: 'LIBRARY.ERRORS.CONFLICT'
});
}
} catch (error) {
}
return error;
}
private async checkLibraryNameExists(libraryTitle: string) {
let entries = [];
try {
entries = (await this.findLibraryByTitle(libraryTitle)).list.entries;
} catch {
entries = [];
}
if (entries.length) {
this.libraryTitleExists = entries[0].entry.title.toLowerCase() === libraryTitle.toLowerCase();
} else {
this.libraryTitleExists = false;
}
}
private findLibraryByTitle(libraryTitle: string): Promise<SitePaging> {
return this.queriesApi.findSites(libraryTitle, {
maxItems: 1,
fields: ['title']
});
}
private forbidSpecialCharacters({ value }: FormControl) {
if (value === null || value.length === 0) {
return null;
}
const validCharacters: RegExp = /[^A-Za-z0-9-]/;
const isValid: boolean = !validCharacters.test(value);
return isValid
? null
: {
message: 'LIBRARY.ERRORS.ILLEGAL_CHARACTERS'
};
}
private forbidOnlySpaces({ value }: FormControl) {
if (value === null || value.length === 0) {
return null;
}
const isValid: boolean = !!(value || '').trim();
return isValid
? null
: {
message: 'LIBRARY.ERRORS.ONLY_SPACES'
};
}
private createSiteIdValidator() {
let timer;
return (control: AbstractControl) => {
if (timer) {
clearTimeout(timer);
}
return new Promise((resolve) => {
timer = setTimeout(() => {
return this.sitesService.getSite(control.value).subscribe(
() => resolve({ message: 'LIBRARY.ERRORS.EXISTENT_SITE' }),
() => resolve(null)
);
}, 300);
});
};
}
}

View File

@@ -19,8 +19,7 @@ import moment from 'moment-es6';
import { TestBed, fakeAsync, tick, ComponentFixture } from '@angular/core/testing';
import { MatDialogRef } from '@angular/material/dialog';
import { AlfrescoApiService, setupTestBed } from '@alfresco/adf-core';
import { NodeBodyLock } from '@alfresco/js-api';
import { setupTestBed } from '@alfresco/adf-core';
import { NodeLockDialogComponent } from './node-lock.dialog';
import { ContentTestingModule } from '../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
@@ -29,7 +28,6 @@ describe('NodeLockDialogComponent', () => {
let fixture: ComponentFixture<NodeLockDialogComponent>;
let component: NodeLockDialogComponent;
let alfrescoApi: AlfrescoApiService;
let expiryDate;
const dialogRef = {
close: jasmine.createSpy('close')
@@ -48,7 +46,6 @@ describe('NodeLockDialogComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(NodeLockDialogComponent);
component = fixture.componentInstance;
alfrescoApi = TestBed.inject(AlfrescoApiService);
});
afterEach(() => {
@@ -98,33 +95,9 @@ describe('NodeLockDialogComponent', () => {
expect(component.form.value.time.format()).toBe(newTime.format());
});
it('should submit the form and lock the node', () => {
spyOn(alfrescoApi.nodesApi, 'lockNode').and.returnValue(Promise.resolve(null));
component.submit();
expect(alfrescoApi.nodesApi.lockNode).toHaveBeenCalledWith(
'node-id',
new NodeBodyLock({
'timeToExpire': 60,
'type': 'ALLOW_OWNER_CHANGES',
'lifetime': 'PERSISTENT'
})
);
});
it('should submit the form and unlock the node', () => {
spyOn(alfrescoApi.nodesApi, 'unlockNode').and.returnValue(Promise.resolve(null));
component.form.controls['isLocked'].setValue(false);
component.submit();
expect(alfrescoApi.nodesApi.unlockNode).toHaveBeenCalledWith('node-id');
});
it('should call dialog to close with form data when submit is successfully', fakeAsync(() => {
const node: any = { entry: {} };
spyOn(alfrescoApi.nodesApi, 'lockNode').and.returnValue(Promise.resolve(node));
spyOn(component['nodesApi'], 'lockNode').and.returnValue(Promise.resolve(node));
component.submit();
tick();
@@ -134,7 +107,7 @@ describe('NodeLockDialogComponent', () => {
}));
it('should call onError if submit fails', fakeAsync(() => {
spyOn(alfrescoApi.nodesApi, 'lockNode').and.returnValue(Promise.reject('error'));
spyOn(component['nodesApi'], 'lockNode').and.returnValue(Promise.reject('error'));
spyOn(component.data, 'onError');
component.submit();

View File

@@ -21,7 +21,7 @@ import { Component, Inject, OnInit, Optional, ViewEncapsulation } from '@angular
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { FormBuilder, FormGroup } from '@angular/forms';
import { NodeBodyLock, Node, NodeEntry } from '@alfresco/js-api';
import { NodeBodyLock, Node, NodeEntry, NodesApi } from '@alfresco/js-api';
import { AlfrescoApiService } from '@alfresco/adf-core';
@Component({
@@ -35,6 +35,8 @@ export class NodeLockDialogComponent implements OnInit {
node: Node = null;
nodeName: string;
private nodesApi: NodesApi;
constructor(
private formBuilder: FormBuilder,
public dialog: MatDialogRef<NodeLockDialogComponent>,
@@ -43,6 +45,7 @@ export class NodeLockDialogComponent implements OnInit {
@Inject(MAT_DIALOG_DATA)
public data: any
) {
this.nodesApi = new NodesApi(this.alfrescoApi.getInstance());
}
ngOnInit() {
@@ -75,13 +78,13 @@ export class NodeLockDialogComponent implements OnInit {
}
private toggleLock(): Promise<NodeEntry> {
const { alfrescoApi: { nodesApi }, data: { node } } = this;
const { data: { node } } = this;
if (this.form.value.isLocked) {
return nodesApi.lockNode(node.id, this.nodeBodyLock);
return this.nodesApi.lockNode(node.id, this.nodeBodyLock);
}
return nodesApi.unlockNode(node.id);
return this.nodesApi.unlockNode(node.id);
}
submit(): void {

View File

@@ -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';

View File

@@ -48,7 +48,7 @@ import {
DataRow
} from '@alfresco/adf-core';
import { Node, NodeEntry, NodePaging, Pagination } from '@alfresco/js-api';
import { Node, NodeEntry, NodePaging, NodesApi, Pagination } from '@alfresco/js-api';
import { Subject, BehaviorSubject, of } from 'rxjs';
import { ShareDataRow } from './../data/share-data-row.model';
import { ShareDataTableAdapter } from './../data/share-datatable-adapter';
@@ -342,6 +342,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
private rowMenuCache: { [key: string]: ContentActionModel[] } = {};
private loadingTimeout;
private onDestroy$ = new Subject<boolean>();
private nodesApi: NodesApi;
constructor(private documentListService: DocumentListService,
private ngZone: NgZone,
@@ -352,6 +353,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
private thumbnailService: ThumbnailService,
private alfrescoApiService: AlfrescoApiService,
private lockService: LockService) {
this.nodesApi = new NodesApi(this.alfrescoApiService.getInstance());
this.userPreferencesService
.select(UserPreferenceValues.PaginationSize)
.pipe(takeUntil(this.onDestroy$))
@@ -801,7 +803,7 @@ export class DocumentListComponent implements OnInit, OnChanges, OnDestroy, Afte
include: this.includeFields
};
this.alfrescoApiService.nodesApi.getNode(nodeEntry.entry['guid'], options)
this.nodesApi.getNode(nodeEntry.entry['guid'], options)
.then((node: NodeEntry) => {
this.navigateTo(node.entry);
});

View File

@@ -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());
}
/**

View File

@@ -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']);

View File

@@ -20,7 +20,7 @@ import {
} from '@alfresco/adf-core';
import { Injectable } from '@angular/core';
import { NodeEntry, NodePaging } from '@alfresco/js-api';
import { NodeEntry, NodePaging, NodesApi } from '@alfresco/js-api';
import { DocumentLoaderNode } from '../models/document-folder.model';
import { Observable, from, throwError, forkJoin } from 'rxjs';
import { catchError, map } from 'rxjs/operators';
@@ -34,10 +34,13 @@ export class DocumentListService implements DocumentListLoader {
static ROOT_ID = '-root-';
nodes: NodesApi;
constructor(private contentService: ContentService,
private apiService: AlfrescoApiService,
private logService: LogService,
private customResourcesService: CustomResourcesService) {
this.nodes = new NodesApi(this.apiService.getInstance());
}
/**
@@ -46,7 +49,7 @@ export class DocumentListService implements DocumentListLoader {
* @returns Empty response when the operation is complete
*/
deleteNode(nodeId: string): Observable<any> {
return from(this.apiService.getInstance().nodes.deleteNode(nodeId));
return from(this.nodes.deleteNode(nodeId));
}
/**
@@ -57,7 +60,7 @@ export class DocumentListService implements DocumentListLoader {
* @returns NodeEntry for the copied node
*/
copyNode(nodeId: string, targetParentId: string): Observable<NodeEntry> {
return from(this.apiService.getInstance().nodes.copyNode(nodeId, { targetParentId })).pipe(
return from(this.nodes.copyNode(nodeId, { targetParentId })).pipe(
catchError((err) => this.handleError(err))
);
}
@@ -70,7 +73,7 @@ export class DocumentListService implements DocumentListLoader {
* @returns NodeEntry for the moved node
*/
moveNode(nodeId: string, targetParentId: string): Observable<NodeEntry> {
return from(this.apiService.getInstance().nodes.moveNode(nodeId, { targetParentId })).pipe(
return from(this.nodes.moveNode(nodeId, { targetParentId })).pipe(
catchError((err) => this.handleError(err))
);
}
@@ -115,7 +118,7 @@ export class DocumentListService implements DocumentListLoader {
}
}
return from(this.apiService.getInstance().nodes.getNodeChildren(rootNodeId, params)).pipe(
return from(this.nodes.listNodeChildren(rootNodeId, params)).pipe(
catchError((err) => this.handleError(err))
);
}
@@ -153,7 +156,7 @@ export class DocumentListService implements DocumentListLoader {
include: includeFieldsRequest
};
return from(this.apiService.getInstance().nodes.getNode(nodeId, opts)).pipe(
return from(this.nodes.getNode(nodeId, opts)).pipe(
catchError((err) => this.handleError(err))
);
}

View File

@@ -16,19 +16,24 @@
*/
import { Injectable } from '@angular/core';
import { GroupEntry } from '@alfresco/js-api';
import { GroupEntry, GroupsApi } from '@alfresco/js-api';
import { AlfrescoApiService } from '@alfresco/adf-core';
@Injectable({
providedIn: 'root'
})
export class GroupService {
groupsApi: GroupsApi;
constructor(
private alfrescoApiService: AlfrescoApiService
) {}
) {
this.groupsApi = new GroupsApi(this.alfrescoApiService.getInstance());
}
async listAllGroupMembershipsForPerson(personId: string, opts?: any, accumulator = []): Promise<GroupEntry[]> {
const groupsPaginated = await this.alfrescoApiService.groupsApi.listGroupMembershipsForPerson(personId, opts);
const groupsPaginated = await this.groupsApi.listGroupMembershipsForPerson(personId, opts);
accumulator = [...accumulator, ...groupsPaginated.list.entries];
if (groupsPaginated.list.pagination.hasMoreItems) {
const skip = groupsPaginated.list.pagination.skipCount + groupsPaginated.list.pagination.count;

View File

@@ -15,8 +15,22 @@
* limitations under the License.
*/
import { AlfrescoApiService, NodesApiService, SearchService, TranslationService, EcmUserModel } from '@alfresco/adf-core';
import { Group, GroupMemberEntry, GroupMemberPaging, Node, PathElement, PermissionElement, QueryBody } from '@alfresco/js-api';
import {
AlfrescoApiService,
NodesApiService,
SearchService,
TranslationService,
EcmUserModel
} from '@alfresco/adf-core';
import {
Group,
GroupMemberEntry,
GroupMemberPaging, GroupsApi,
Node,
PathElement,
PermissionElement,
QueryBody
} from '@alfresco/js-api';
import { Injectable } from '@angular/core';
import { forkJoin, from, Observable, of, throwError } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';
@@ -28,10 +42,13 @@ import { RoleModel } from '../models/role.model';
})
export class NodePermissionService {
groupsApi: GroupsApi;
constructor(private apiService: AlfrescoApiService,
private searchApiService: SearchService,
private nodeService: NodesApiService,
private translation: TranslationService) {
this.groupsApi = new GroupsApi(this.apiService.getInstance());
}
/**
@@ -44,7 +61,7 @@ export class NodePermissionService {
return this.searchApiService.searchByQueryBody(retrieveSiteQueryBody)
.pipe(
switchMap((siteNodeList: any) => {
if ( siteNodeList.list.entries.length > 0 ) {
if (siteNodeList.list.entries.length > 0) {
const siteName = siteNodeList.list.entries[0].entry.name;
return this.getGroupMembersBySiteName(siteName);
} else {
@@ -80,7 +97,7 @@ export class NodePermissionService {
* @returns Node with updated permission
*/
updatePermissionRole(node: Node, updatedPermissionRole: PermissionElement): Observable<Node> {
const permissionBody = { permissions: { locallySet: []} };
const permissionBody = { permissions: { locallySet: [] } };
const index = node.permissions.locallySet.map((permission) => permission.authorityId).indexOf(updatedPermissionRole.authorityId);
permissionBody.permissions.locallySet = permissionBody.permissions.locallySet.concat(node.permissions.locallySet);
if (index !== -1) {
@@ -98,7 +115,7 @@ export class NodePermissionService {
* @returns Node with updated permissions
*/
updateNodePermissions(nodeId: string, permissionList: PermissionElement[]): Observable<Node> {
return this.nodeService.getNode(nodeId).pipe(
return this.nodeService.getNode(nodeId).pipe(
switchMap((node) => this.updateLocallySetPermissions(node, permissionList))
);
}
@@ -110,12 +127,12 @@ export class NodePermissionService {
* @returns Node with updated permissions
*/
updateLocallySetPermissions(node: Node, permissions: PermissionElement[]): Observable<Node> {
const permissionBody = { permissions: { locallySet: []} };
const permissionBody = { permissions: { locallySet: [] } };
const permissionList = permissions;
const duplicatedPermissions = this.getDuplicatedPermissions(node.permissions.locallySet, permissionList);
if (duplicatedPermissions.length > 0) {
const list = duplicatedPermissions.map((permission) => 'authority -> ' + permission.authorityId + ' / role -> ' + permission.name).join(', ');
const duplicatePermissionMessage: string = this.translation.instant('PERMISSION_MANAGER.ERROR.DUPLICATE-PERMISSION', {list});
const duplicatePermissionMessage: string = this.translation.instant('PERMISSION_MANAGER.ERROR.DUPLICATE-PERMISSION', { list });
return throwError(duplicatePermissionMessage);
}
permissionBody.permissions.locallySet = node.permissions.locallySet ? node.permissions.locallySet.concat(permissionList) : permissionList;
@@ -137,8 +154,8 @@ export class NodePermissionService {
private isEqualPermission(oldPermission: PermissionElement, newPermission: PermissionElement): boolean {
return oldPermission.accessStatus === newPermission.accessStatus &&
oldPermission.authorityId === newPermission.authorityId &&
oldPermission.name === newPermission.name;
oldPermission.authorityId === newPermission.authorityId &&
oldPermission.name === newPermission.name;
}
/**
@@ -181,7 +198,7 @@ export class NodePermissionService {
* @returns List of members
*/
getGroupMemberByGroupName(groupName: string, opts?: any): Observable<GroupMemberPaging> {
return from(this.apiService.groupsApi.listGroupMemberships(groupName, opts));
return from(this.groupsApi.listGroupMemberships(groupName, opts));
}
private formattedRoleName(displayName, siteName): string {
@@ -245,10 +262,10 @@ export class NodePermissionService {
const permissionBody = { permissions: { locallySet: [] } };
permissions.forEach((permission) => {
const index = node.permissions.locallySet.findIndex((locallySet) => locallySet.authorityId === permission.authorityId);
if (index !== -1) {
node.permissions.locallySet.splice(index, 1);
}
const index = node.permissions.locallySet.findIndex((locallySet) => locallySet.authorityId === permission.authorityId);
if (index !== -1) {
node.permissions.locallySet.splice(index, 1);
}
});
permissionBody.permissions.locallySet = node.permissions.locallySet;
return this.nodeService.updateNode(node.id, permissionBody);
@@ -271,37 +288,37 @@ export class NodePermissionService {
* @param nodeId Id of the node
* @returns node and it's associated roles { node: Node; roles: RoleModel[] }
*/
getNodeWithRoles(nodeId: string): Observable<{ node: Node; roles: RoleModel[] }> {
return this.nodeService.getNode(nodeId).pipe(
getNodeWithRoles(nodeId: string): Observable<{ node: Node; roles: RoleModel[] }> {
return this.nodeService.getNode(nodeId).pipe(
switchMap(node => {
return forkJoin({
node: of(node),
roles: this.getNodeRoles(node)
.pipe(
catchError(() => of(node.permissions?.settable)),
map(_roles => _roles.map(role => ({ role, label: role }))
)
)
});
})
);
}
node: of(node),
roles: this.getNodeRoles(node)
.pipe(
catchError(() => of(node.permissions?.settable)),
map(_roles => _roles.map(role => ({ role, label: role }))
)
)
});
})
);
}
transformNodeToUserPerson(node: Node): { person: EcmUserModel, group: Group } {
let person = null, group = null;
if (node.nodeType === 'cm:person') {
const firstName = node.properties['cm:firstName'];
const lastName = node.properties['cm:lastName'];
const email = node.properties['cm:email'];
const id = node.properties['cm:userName'];
person = new EcmUserModel({ id, firstName, lastName, email});
}
transformNodeToUserPerson(node: Node): { person: EcmUserModel, group: Group } {
let person = null, group = null;
if (node.nodeType === 'cm:person') {
const firstName = node.properties['cm:firstName'];
const lastName = node.properties['cm:lastName'];
const email = node.properties['cm:email'];
const id = node.properties['cm:userName'];
person = new EcmUserModel({ id, firstName, lastName, email });
}
if (node.nodeType === 'cm:authorityContainer') {
const displayName = node.properties['cm:authorityDisplayName'] || node.properties['cm:authorityName'];
const id = node.properties['cm:authorityName'];
group = new Group({ displayName, id });
}
return { person, group };
}
if (node.nodeType === 'cm:authorityContainer') {
const displayName = node.properties['cm:authorityDisplayName'] || node.properties['cm:authorityName'];
const id = node.properties['cm:authorityName'];
group = new Group({ displayName, id });
}
return { person, group };
}
}

View File

@@ -17,10 +17,10 @@
import { Subject } from 'rxjs';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateModule } from '@ngx-translate/core';
import { SearchService, setupTestBed, AlfrescoApiService } from '@alfresco/adf-core';
import { SearchService, setupTestBed } from '@alfresco/adf-core';
import { SearchHeaderQueryBuilderService } from '../../services/search-header-query-builder.service';
import { ContentTestingModule } from '../../../testing/content.testing.module';
import { fakeNodePaging } from './../../../mock/document-list.component.mock';
// import { fakeNodePaging } from './../../../mock/document-list.component.mock';
import { SEARCH_QUERY_SERVICE_TOKEN } from '../../search-query-service.token';
import { By } from '@angular/platform-browser';
import { SearchFilterContainerComponent } from './search-filter-container.component';
@@ -47,7 +47,6 @@ describe('SearchFilterContainerComponent', () => {
let fixture: ComponentFixture<SearchFilterContainerComponent>;
let component: SearchFilterContainerComponent;
let queryBuilder: SearchHeaderQueryBuilderService;
let alfrescoApiService: AlfrescoApiService;
const searchMock: any = {
dataLoaded: new Subject()
@@ -68,7 +67,6 @@ describe('SearchFilterContainerComponent', () => {
fixture = TestBed.createComponent(SearchFilterContainerComponent);
component = fixture.componentInstance;
queryBuilder = fixture.componentInstance['searchFilterQueryBuilder'];
alfrescoApiService = TestBed.inject(AlfrescoApiService);
component.col = {key: '123', type: 'text'};
spyOn(queryBuilder, 'getCategoryForColumn').and.returnValue(mockCategory);
fixture.detectChanges();
@@ -113,23 +111,6 @@ describe('SearchFilterContainerComponent', () => {
expect(queryBuilder.getActiveFilters()[0].value).toBe('updated text');
});
it('should emit filterChange after the Apply button is clicked', async (done) => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(Promise.resolve(fakeNodePaging));
spyOn(queryBuilder, 'buildQuery').and.returnValue(null);
component.filterChange.subscribe(() => {
done();
});
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('#filter-menu-button');
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
component.widgetContainer.componentRef.instance.value = 'searchText';
const applyButton = fixture.debugElement.query(By.css('#apply-filter-button'));
applyButton.triggerEventHandler('click', {});
fixture.detectChanges();
await fixture.whenStable();
});
it('should remove active filter after the Clear button is clicked', async () => {
queryBuilder.setActiveFilter('name', 'searchText');
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('#filter-menu-button');
@@ -145,24 +126,6 @@ describe('SearchFilterContainerComponent', () => {
expect(queryBuilder.getActiveFilters().length).toBe(0);
});
it('should emit filterChange after the Clear button is clicked', async (done) => {
spyOn(alfrescoApiService.searchApi, 'search').and.returnValue(Promise.resolve(fakeNodePaging));
spyOn(queryBuilder, 'buildQuery').and.returnValue(null);
component.filterChange.subscribe(() => {
done();
});
const menuButton: HTMLButtonElement = fixture.nativeElement.querySelector('#filter-menu-button');
menuButton.click();
fixture.detectChanges();
await fixture.whenStable();
component.widgetContainer.componentRef.instance.value = 'searchText';
const fakeEvent = jasmine.createSpyObj('event', ['stopPropagation']);
const clearButton = fixture.debugElement.query(By.css('#clear-filter-button'));
clearButton.triggerEventHandler('click', fakeEvent);
fixture.detectChanges();
await fixture.whenStable();
});
it('should emit filterChange after the Enter key is pressed', async (done) => {
spyOn(queryBuilder, 'buildQuery').and.returnValue(null);
component.filterChange.subscribe(() => {

View File

@@ -25,7 +25,8 @@ import {
RequestSortDefinitionInner,
ResultSetPaging,
RequestHighlight,
RequestScope
RequestScope,
SearchApi
} from '@alfresco/js-api';
import { SearchCategory } from '../models/search-category.interface';
import { FilterQuery } from '../models/filter-query.interface';
@@ -284,7 +285,8 @@ export abstract class BaseQueryBuilderService {
try {
const query = queryBody ? queryBody : this.buildQuery();
if (query) {
const resultSetPaging: ResultSetPaging = await this.alfrescoApiService.getInstance().search.searchApi.search(query);
const searchApi = new SearchApi(this.alfrescoApiService.getInstance());
const resultSetPaging: ResultSetPaging = await searchApi.search(query);
this.executed.next(resultSetPaging);
}
} catch (error) {
@@ -302,7 +304,8 @@ export abstract class BaseQueryBuilderService {
}
search(queryBody: QueryBody): Observable<ResultSetPaging> {
const promise = this.alfrescoApiService.searchApi.search(queryBody);
const searchApi = new SearchApi(this.alfrescoApiService.getInstance());
const promise = searchApi.search(queryBody);
promise.then((resultSetPaging) => {
this.executed.next(resultSetPaging);
@@ -410,7 +413,7 @@ export abstract class BaseQueryBuilderService {
}
get hasFacetHighlight(): boolean {
return this.config && this.config.highlight ? true : false;
return !!(this.config && this.config.highlight);
}
protected get sort(): RequestSortDefinitionInner[] {

View File

@@ -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 => {

View File

@@ -17,7 +17,7 @@
import { AlfrescoApiService, LogService } from '@alfresco/adf-core';
import { Injectable } from '@angular/core';
import { RatingEntry, RatingBody } from '@alfresco/js-api';
import { RatingEntry, RatingBody, RatingsApi } from '@alfresco/js-api';
import { from, throwError, Observable } from 'rxjs';
import { catchError } from 'rxjs/operators';
@@ -26,7 +26,10 @@ import { catchError } from 'rxjs/operators';
})
export class RatingService {
ratingsApi: RatingsApi;
constructor(private apiService: AlfrescoApiService, private logService: LogService) {
this.ratingsApi = new RatingsApi(this.apiService.getInstance());
}
/**
@@ -36,7 +39,7 @@ export class RatingService {
* @returns The rating value
*/
getRating(nodeId: string, ratingType: any): Observable<RatingEntry | {}> {
return from(this.apiService.getInstance().core.ratingsApi.getRating(nodeId, ratingType))
return from(this.ratingsApi.getRating(nodeId, ratingType))
.pipe(
catchError(this.handleError)
);
@@ -54,7 +57,7 @@ export class RatingService {
'id': ratingType,
'myRating': vote
});
return from(this.apiService.getInstance().core.ratingsApi.rate(nodeId, ratingBody))
return from(this.ratingsApi.createRating(nodeId, ratingBody))
.pipe(
catchError(this.handleError)
);
@@ -67,7 +70,7 @@ export class RatingService {
* @returns Null response indicating that the operation is complete
*/
deleteRating(nodeId: string, ratingType: any): Observable<any> {
return from(this.apiService.getInstance().core.ratingsApi.removeRating(nodeId, ratingType))
return from(this.ratingsApi.deleteRating(nodeId, ratingType))
.pipe(
catchError(this.handleError)
);

View File

@@ -19,7 +19,7 @@ import { AlfrescoApiService, LogService } from '@alfresco/adf-core';
import { EventEmitter, Injectable, Output } from '@angular/core';
import { Observable, from, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { TagBody, TagPaging, TagEntry } from '@alfresco/js-api';
import { TagBody, TagPaging, TagEntry, TagsApi } from '@alfresco/js-api';
@Injectable({
providedIn: 'root'
@@ -27,12 +27,15 @@ import { TagBody, TagPaging, TagEntry } from '@alfresco/js-api';
// tslint:disable-next-line: directive-class-suffix
export class TagService {
private tagsApi: TagsApi;
/** Emitted when tag information is updated. */
@Output()
refresh = new EventEmitter();
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.tagsApi = new TagsApi(this.apiService.getInstance());
}
/**
@@ -41,7 +44,7 @@ export class TagService {
* @returns TagPaging object (defined in JS-API) containing the tags
*/
getTagsByNodeId(nodeId: string): Observable<TagPaging> {
return from(this.apiService.getInstance().core.tagsApi.getNodeTags(nodeId)).pipe(
return from(this.tagsApi.listTagsForNode(nodeId)).pipe(
catchError((err) => this.handleError(err))
);
}
@@ -52,7 +55,7 @@ export class TagService {
* @returns TagPaging object (defined in JS-API) containing the tags
*/
getAllTheTags(opts?: any): Observable<TagPaging> {
return from(this.apiService.getInstance().core.tagsApi.getTags(opts))
return from(this.tagsApi.listTags(opts))
.pipe(catchError((err) => this.handleError(err)));
}
@@ -66,7 +69,7 @@ export class TagService {
const tagBody = new TagBody();
tagBody.tag = tagName;
const observableAdd = from(this.apiService.getInstance().core.tagsApi.addTag(nodeId, [tagBody]));
const observableAdd = from(this.tagsApi.createTagForNode(nodeId, [tagBody]));
observableAdd.subscribe((tagEntry: TagEntry) => {
this.refresh.emit(tagEntry);
@@ -84,7 +87,7 @@ export class TagService {
* @returns Null object when the operation completes
*/
removeTag(nodeId: string, tag: string): Observable<any> {
const observableRemove = from(this.apiService.getInstance().core.tagsApi.removeTag(nodeId, tag));
const observableRemove = from(this.tagsApi.deleteTagFromNode(nodeId, tag));
observableRemove.subscribe((data) => {
this.refresh.emit(data);

View File

@@ -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);

View File

@@ -19,17 +19,16 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { VersionListComponent } from './version-list.component';
import { AlfrescoApiService, setupTestBed } from '@alfresco/adf-core';
import { setupTestBed } from '@alfresco/adf-core';
import { MatDialog } from '@angular/material/dialog';
import { of } from 'rxjs';
import { Node, VersionPaging, VersionEntry } from '@alfresco/js-api';
import { Node, VersionPaging, VersionEntry, NodeEntry } from '@alfresco/js-api';
import { ContentTestingModule } from '../testing/content.testing.module';
import { TranslateModule } from '@ngx-translate/core';
describe('VersionListComponent', () => {
let component: VersionListComponent;
let fixture: ComponentFixture<VersionListComponent>;
let alfrescoApiService: AlfrescoApiService;
let dialog: MatDialog;
const nodeId = 'test-id';
@@ -59,14 +58,13 @@ describe('VersionListComponent', () => {
beforeEach(() => {
fixture = TestBed.createComponent(VersionListComponent);
alfrescoApiService = TestBed.inject(AlfrescoApiService);
dialog = TestBed.inject(MatDialog);
component = fixture.componentInstance;
component.node = <Node> { id: nodeId, allowableOperations: ['update'] };
spyOn(component, 'downloadContent').and.stub();
spyOn(alfrescoApiService.nodesApi, 'getNodeInfo').and.returnValue(Promise.resolve(<Node> { id: 'nodeInfoId' }));
spyOn(component['nodesApi'], 'getNode').and.returnValue(Promise.resolve(<NodeEntry> { entry: { id: 'nodeInfoId' } }));
});
it('should raise confirmation dialog on delete', () => {
@@ -93,12 +91,12 @@ describe('VersionListComponent', () => {
}
} as any);
spyOn(alfrescoApiService.versionsApi, 'deleteVersion').and.returnValue(Promise.resolve(true));
spyOn(component['versionsApi'], 'deleteVersion').and.returnValue(Promise.resolve(true));
component.deleteVersion(versionId);
expect(dialog.open).toHaveBeenCalled();
expect(alfrescoApiService.versionsApi.deleteVersion).toHaveBeenCalledWith(nodeId, versionId);
expect(component['versionsApi'].deleteVersion).toHaveBeenCalledWith(nodeId, versionId);
});
it('should not delete version if user rejects', () => {
@@ -110,12 +108,12 @@ describe('VersionListComponent', () => {
}
} as any);
spyOn(alfrescoApiService.versionsApi, 'deleteVersion').and.returnValue(Promise.resolve(true));
spyOn(component['versionsApi'], 'deleteVersion').and.returnValue(Promise.resolve(true));
component.deleteVersion(versionId);
expect(dialog.open).toHaveBeenCalled();
expect(alfrescoApiService.versionsApi.deleteVersion).not.toHaveBeenCalled();
expect(component['versionsApi'].deleteVersion).not.toHaveBeenCalled();
});
it('should reload and raise deleted event', (done) => {
@@ -131,7 +129,7 @@ describe('VersionListComponent', () => {
describe('Version history fetching', () => {
it('should use loading bar', () => {
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and
spyOn(component['versionsApi'], 'listVersionHistory').and
.callFake(() => Promise.resolve({ list: { entries: versionTest } }));
let loadingProgressBar = fixture.debugElement.query(By.css('[data-automation-id="version-history-loading-bar"]'));
@@ -145,18 +143,18 @@ describe('VersionListComponent', () => {
});
it('should load the versions for a given id', () => {
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and
spyOn(component['versionsApi'], 'listVersionHistory').and
.callFake(() => Promise.resolve({ list: { entries: versionTest } }));
component.ngOnChanges();
fixture.detectChanges();
expect(alfrescoApiService.versionsApi.listVersionHistory).toHaveBeenCalledWith(nodeId);
expect(component['versionsApi'].listVersionHistory).toHaveBeenCalledWith(nodeId);
});
it('should show the versions after loading', (done) => {
fixture.detectChanges();
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and.callFake(() => {
spyOn(component['versionsApi'], 'listVersionHistory').and.callFake(() => {
return Promise.resolve(new VersionPaging({
list: {
entries: [
@@ -184,7 +182,7 @@ describe('VersionListComponent', () => {
});
it('should NOT show the versions comments if input property is set not to show them', (done) => {
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and
spyOn(component['versionsApi'], 'listVersionHistory').and
.callFake(() => Promise.resolve(
new VersionPaging({
list: {
@@ -219,13 +217,13 @@ describe('VersionListComponent', () => {
versionComment: 'test-version-comment'
}
};
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and.returnValue(Promise.resolve(new VersionPaging({ list: { entries: [versionEntry] } })));
spyOn(alfrescoApiService.contentApi, 'getContentUrl').and.returnValue('the/download/url');
spyOn(component['versionsApi'], 'listVersionHistory').and.returnValue(Promise.resolve(new VersionPaging({ list: { entries: [versionEntry] } })));
spyOn(component['contentApi'], 'getContentUrl').and.returnValue('the/download/url');
fixture.detectChanges();
component.downloadVersion('1.0');
expect(alfrescoApiService.contentApi.getContentUrl).toHaveBeenCalledWith(nodeId, true);
expect(component['contentApi'].getContentUrl).toHaveBeenCalledWith(nodeId, true);
});
it('should be able to view a version', () => {
@@ -243,9 +241,9 @@ describe('VersionListComponent', () => {
versionComment: 'test-version-comment'
}
};
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and
spyOn(component['versionsApi'], 'listVersionHistory').and
.callFake(() => Promise.resolve(new VersionPaging({ list: { entries: [versionEntry] } })));
const spyOnDownload = spyOn(alfrescoApiService.contentApi, 'getContentUrl').and.stub();
const spyOnDownload = spyOn(component['contentApi'], 'getContentUrl').and.stub();
component.allowDownload = false;
fixture.detectChanges();
@@ -253,32 +251,22 @@ describe('VersionListComponent', () => {
component.downloadVersion('1.0');
expect(spyOnDownload).not.toHaveBeenCalled();
});
});
});
describe('Version restoring', () => {
it('should reload and raise version-restored DOM event', (done) => {
spyOn(component, 'loadVersionHistory').and.stub();
component.restored.subscribe(() => {
expect(component.loadVersionHistory).toHaveBeenCalled();
done();
});
fixture.detectChanges();
component.onVersionRestored({});
});
it('should restore version only when restore allowed', () => {
component.node.allowableOperations = [];
spyOn(alfrescoApiService.versionsApi, 'revertVersion').and.stub();
spyOn(component['versionsApi'], 'revertVersion').and.stub();
component.restore('1');
expect(alfrescoApiService.versionsApi.revertVersion).not.toHaveBeenCalled();
expect(component['versionsApi'].revertVersion).not.toHaveBeenCalled();
});
it('should load the versions for a given id', () => {
fixture.detectChanges();
component.versions = versionTest;
const spyOnRevertVersion = spyOn(alfrescoApiService.versionsApi, 'revertVersion').and
const spyOnRevertVersion = spyOn(component['versionsApi'], 'revertVersion').and
.callFake(() => Promise.resolve(new VersionEntry(
{ entry: { name: 'test-file-name', id: '1.0', versionComment: 'test-version-comment' } })));
@@ -290,29 +278,29 @@ describe('VersionListComponent', () => {
it('should get node info after restoring the node', fakeAsync(() => {
fixture.detectChanges();
component.versions = versionTest;
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory')
spyOn(component['versionsApi'], 'listVersionHistory')
.and.callFake(() => Promise.resolve({ list: { entries: versionTest } }));
spyOn(alfrescoApiService.versionsApi, 'revertVersion')
spyOn(component['versionsApi'], 'revertVersion')
.and.callFake(() => Promise.resolve(new VersionEntry(
{ entry: { name: 'test-file-name', id: '1.0', versionComment: 'test-version-comment' } })));
{ entry: { name: 'test-file-name', id: '1.0', versionComment: 'test-version-comment' } })));
component.restore(versionId);
fixture.detectChanges();
tick();
expect(alfrescoApiService.nodesApi.getNodeInfo).toHaveBeenCalled();
expect(component['nodesApi'].getNode).toHaveBeenCalled();
}));
it('should emit with node info data', fakeAsync(() => {
fixture.detectChanges();
component.versions = versionTest;
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory')
spyOn(component['versionsApi'], 'listVersionHistory')
.and.callFake(() => Promise.resolve({ list: { entries: versionTest } }));
spyOn(alfrescoApiService.versionsApi, 'revertVersion')
spyOn(component['versionsApi'], 'revertVersion')
.and.callFake(() => Promise.resolve(new VersionEntry(
{ entry: { name: 'test-file-name', id: '1.0', versionComment: 'test-version-comment' } })));
{ entry: { name: 'test-file-name', id: '1.0', versionComment: 'test-version-comment' } })));
spyOn(component.restored, 'emit');
@@ -327,9 +315,9 @@ describe('VersionListComponent', () => {
fixture.detectChanges();
component.versions = versionTest;
const spyOnListVersionHistory = spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and
const spyOnListVersionHistory = spyOn(component['versionsApi'], 'listVersionHistory').and
.callFake(() => Promise.resolve({ list: { entries: versionTest } }));
spyOn(alfrescoApiService.versionsApi, 'revertVersion').and.callFake(() => Promise.resolve(null));
spyOn(component['versionsApi'], 'revertVersion').and.callFake(() => Promise.resolve(null));
component.restore(versionId);
fixture.detectChanges();
@@ -346,7 +334,7 @@ describe('VersionListComponent', () => {
beforeEach(() => {
fixture.detectChanges();
component.node = new Node({ id: nodeId });
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and.callFake(() => {
spyOn(component['versionsApi'], 'listVersionHistory').and.callFake(() => {
return Promise.resolve(new VersionPaging({
list: {
entries: [
@@ -395,7 +383,7 @@ describe('VersionListComponent', () => {
beforeEach(() => {
fixture.detectChanges();
component.node = <Node> { id: nodeId };
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and.callFake(() => {
spyOn(component['versionsApi'], 'listVersionHistory').and.callFake(() => {
return Promise.resolve(new VersionPaging({
list: {
entries: [
@@ -445,7 +433,7 @@ describe('VersionListComponent', () => {
beforeEach(() => {
fixture.detectChanges();
component.node = <Node> { id: nodeId, allowableOperations: ['update', 'delete'] };
spyOn(alfrescoApiService.versionsApi, 'listVersionHistory').and.callFake(() => {
spyOn(component['versionsApi'], 'listVersionHistory').and.callFake(() => {
return Promise.resolve(new VersionPaging({
list: {
entries: [

View File

@@ -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');
}

View File

@@ -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 ] }})));
});

View File

@@ -17,6 +17,7 @@
import { ObjectDataTableAdapter, AlfrescoApiService, LogService } from '@alfresco/adf-core';
import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core';
import { WebscriptApi } from '@alfresco/js-api';
/**
* <adf-webscript-get [scriptPath]="string"
@@ -80,8 +81,11 @@ export class WebscriptComponent implements OnChanges {
data: any = undefined;
showError: boolean = false;
webscriptApi: WebscriptApi;
constructor(private apiService: AlfrescoApiService,
private logService: LogService) {
this.webscriptApi = new WebscriptApi(this.apiService.getInstance());
}
ngOnChanges() {
@@ -90,7 +94,7 @@ export class WebscriptComponent implements OnChanges {
}
return new Promise<void>((resolve, reject) => {
this.apiService.getInstance().webScript.executeWebScript('GET', this.scriptPath, this.scriptArgs, this.contextRoot, this.servicePath).then((webScriptData) => {
this.webscriptApi.executeWebScript('GET', this.scriptPath, this.scriptArgs, this.contextRoot, this.servicePath).then((webScriptData) => {
this.data = webScriptData;