content api service (#455)

* introduce content-api service

* upgrade files component

* upgrade directives

* upgrade directives

* update directives

* fix profile resolver call ordering issue

* fix reducer

* update services

* extra apis

* update about page

* update preview component

* code updates
This commit is contained in:
Denys Vuika 2018-06-25 08:37:21 +01:00 committed by Cilibiu Bogdan
parent ac6e96530f
commit af547aac31
36 changed files with 551 additions and 392 deletions

View File

@ -79,6 +79,7 @@ import { PaginationDirective } from './directives/pagination.directive';
import { DocumentListDirective } from './directives/document-list.directive';
import { MaterialModule } from './material.module';
import { ExperimentalDirective } from './directives/experimental.directive';
import { ContentApiService } from './services/content-api.service';
@NgModule({
imports: [
@ -149,7 +150,8 @@ import { ExperimentalDirective } from './directives/experimental.directive';
ContentManagementService,
NodeActionsService,
NodePermissionService,
ProfileResolver
ProfileResolver,
ContentApiService
],
entryComponents: [
NodeVersionsDialogComponent

View File

@ -27,10 +27,11 @@ import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Observable } from 'rxjs/Rx';
import { NodesApiService, NotificationService } from '@alfresco/adf-core';
import { NotificationService } from '@alfresco/adf-core';
import { NodeActionsService } from '../services/node-actions.service';
import { NodeCopyDirective } from './node-copy.directive';
import { AppTestingModule } from '../../testing/app-testing.module';
import { ContentApiService } from '../../services/content-api.service';
@Component({
template: '<div [acaCopyNode]="selection"></div>'
@ -44,8 +45,8 @@ describe('NodeCopyDirective', () => {
let component: TestComponent;
let element: DebugElement;
let notificationService: NotificationService;
let nodesApiService: NodesApiService;
let service: NodeActionsService;
let contentApi: ContentApiService;
beforeEach(() => {
TestBed.configureTestingModule({
@ -56,11 +57,12 @@ describe('NodeCopyDirective', () => {
]
});
contentApi = TestBed.get(ContentApiService);
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
element = fixture.debugElement.query(By.directive(NodeCopyDirective));
notificationService = TestBed.get(NotificationService);
nodesApiService = TestBed.get(NodesApiService);
service = TestBed.get(NodeActionsService);
});
@ -233,7 +235,7 @@ describe('NodeCopyDirective', () => {
});
it('should delete the newly created node on Undo action', () => {
spyOn(nodesApiService, 'deleteNode').and.returnValue(Observable.of(null));
spyOn(contentApi, 'deleteNode').and.returnValue(Observable.of(null));
component.selection = [{ entry: { id: 'node-to-copy-id', name: 'name' } }];
const createdItems = [{ entry: { id: 'copy-id', name: 'name' } }];
@ -247,11 +249,11 @@ describe('NodeCopyDirective', () => {
'APP.MESSAGES.INFO.NODE_COPY.SINGULAR', 'APP.ACTIONS.UNDO', 10000
);
expect(nodesApiService.deleteNode).toHaveBeenCalledWith(createdItems[0].entry.id, { permanent: true });
expect(contentApi.deleteNode).toHaveBeenCalledWith(createdItems[0].entry.id, { permanent: true });
});
it('should delete also the node created inside an already existing folder from destination', () => {
const spyOnDeleteNode = spyOn(nodesApiService, 'deleteNode').and.returnValue(Observable.of(null));
const spyOnDeleteNode = spyOn(contentApi, 'deleteNode').and.returnValue(Observable.of(null));
component.selection = [
{ entry: { id: 'node-to-copy-1', name: 'name1' } },
@ -277,7 +279,7 @@ describe('NodeCopyDirective', () => {
});
it('notifies when error occurs on Undo action', () => {
spyOn(nodesApiService, 'deleteNode').and.returnValue(Observable.throw(null));
spyOn(contentApi, 'deleteNode').and.returnValue(Observable.throw(null));
component.selection = [{ entry: { id: 'node-to-copy-id', name: 'name' } }];
const createdItems = [{ entry: { id: 'copy-id', name: 'name' } }];
@ -287,14 +289,14 @@ describe('NodeCopyDirective', () => {
service.contentCopied.next(<any>createdItems);
expect(service.copyNodes).toHaveBeenCalled();
expect(nodesApiService.deleteNode).toHaveBeenCalled();
expect(contentApi.deleteNode).toHaveBeenCalled();
expect(notificationService.openSnackMessageAction['calls'].allArgs())
.toEqual([['APP.MESSAGES.INFO.NODE_COPY.SINGULAR', 'APP.ACTIONS.UNDO', 10000],
['APP.MESSAGES.ERRORS.GENERIC', '', 3000]]);
});
it('notifies when some error of type Error occurs on Undo action', () => {
spyOn(nodesApiService, 'deleteNode').and.returnValue(Observable.throw(new Error('oops!')));
spyOn(contentApi, 'deleteNode').and.returnValue(Observable.throw(new Error('oops!')));
component.selection = [{ entry: { id: 'node-to-copy-id', name: 'name' } }];
const createdItems = [{ entry: { id: 'copy-id', name: 'name' } }];
@ -304,14 +306,14 @@ describe('NodeCopyDirective', () => {
service.contentCopied.next(<any>createdItems);
expect(service.copyNodes).toHaveBeenCalled();
expect(nodesApiService.deleteNode).toHaveBeenCalled();
expect(contentApi.deleteNode).toHaveBeenCalled();
expect(notificationService.openSnackMessageAction['calls'].allArgs())
.toEqual([['APP.MESSAGES.INFO.NODE_COPY.SINGULAR', 'APP.ACTIONS.UNDO', 10000],
['APP.MESSAGES.ERRORS.GENERIC', '', 3000]]);
});
it('notifies permission error when it occurs on Undo action', () => {
spyOn(nodesApiService, 'deleteNode').and.returnValue(Observable.throw(new Error(JSON.stringify({error: {statusCode: 403}}))));
spyOn(contentApi, 'deleteNode').and.returnValue(Observable.throw(new Error(JSON.stringify({error: {statusCode: 403}}))));
component.selection = [{ entry: { id: 'node-to-copy-id', name: 'name' } }];
const createdItems = [{ entry: { id: 'copy-id', name: 'name' } }];
@ -321,7 +323,7 @@ describe('NodeCopyDirective', () => {
service.contentCopied.next(<any>createdItems);
expect(service.copyNodes).toHaveBeenCalled();
expect(nodesApiService.deleteNode).toHaveBeenCalled();
expect(contentApi.deleteNode).toHaveBeenCalled();
expect(notificationService.openSnackMessageAction['calls'].allArgs())
.toEqual([['APP.MESSAGES.INFO.NODE_COPY.SINGULAR', 'APP.ACTIONS.UNDO', 10000],
['APP.MESSAGES.ERRORS.PERMISSION', '', 3000]]);

View File

@ -26,10 +26,11 @@
import { Directive, HostListener, Input } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { TranslationService, NodesApiService, NotificationService } from '@alfresco/adf-core';
import { TranslationService, NotificationService } from '@alfresco/adf-core';
import { MinimalNodeEntity } from 'alfresco-js-api';
import { NodeActionsService } from '../services/node-actions.service';
import { ContentManagementService } from '../services/content-management.service';
import { ContentApiService } from '../../services/content-api.service';
@Directive({
selector: '[acaCopyNode]'
@ -47,9 +48,9 @@ export class NodeCopyDirective {
constructor(
private content: ContentManagementService,
private contentApi: ContentApiService,
private notification: NotificationService,
private nodeActionsService: NodeActionsService,
private nodesApi: NodesApiService,
private translation: TranslationService
) {}
@ -117,7 +118,7 @@ export class NodeCopyDirective {
private deleteCopy(nodes: MinimalNodeEntity[]) {
const batch = this.nodeActionsService.flatten(nodes)
.filter(item => item.entry)
.map(item => this.nodesApi.deleteNode(item.entry.id, { permanent: true }));
.map(item => this.contentApi.deleteNode(item.entry.id, { permanent: true }));
Observable.forkJoin(...batch)
.subscribe(

View File

@ -25,7 +25,6 @@
import { TestBed, ComponentFixture, fakeAsync, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { Component, DebugElement } from '@angular/core';
import { NodeDeleteDirective } from './node-delete.directive';
@ -37,6 +36,8 @@ import {
} from '../../store/actions';
import { map } from 'rxjs/operators';
import { AppTestingModule } from '../../testing/app-testing.module';
import { ContentApiService } from '../../services/content-api.service';
import { Observable } from 'rxjs/Rx';
@Component({
template: '<div [acaDeleteNode]="selection"></div>'
@ -49,8 +50,8 @@ describe('NodeDeleteDirective', () => {
let component: TestComponent;
let fixture: ComponentFixture<TestComponent>;
let element: DebugElement;
let alfrescoApiService: AlfrescoApiService;
let actions$: Actions;
let contentApi: ContentApiService;
beforeEach(() => {
TestBed.configureTestingModule({
@ -64,9 +65,7 @@ describe('NodeDeleteDirective', () => {
]
});
alfrescoApiService = TestBed.get(AlfrescoApiService);
alfrescoApiService.reset();
contentApi = TestBed.get(ContentApiService);
actions$ = TestBed.get(Actions);
fixture = TestBed.createComponent(TestComponent);
@ -76,7 +75,7 @@ describe('NodeDeleteDirective', () => {
describe('Delete action', () => {
it('should raise info message on successful single file deletion', fakeAsync(done => {
spyOn(alfrescoApiService.nodesApi, 'deleteNode').and.returnValue(Promise.resolve(null));
spyOn(contentApi, 'deleteNode').and.returnValue(Observable.of(null));
actions$.pipe(
ofType<SnackbarInfoAction>(SNACKBAR_INFO),
@ -94,7 +93,7 @@ describe('NodeDeleteDirective', () => {
}));
it('should raise error message on failed single file deletion', fakeAsync(done => {
spyOn(alfrescoApiService.nodesApi, 'deleteNode').and.returnValue(Promise.reject(null));
spyOn(contentApi, 'deleteNode').and.returnValue(Observable.throw(null));
actions$.pipe(
ofType<SnackbarErrorAction>(SNACKBAR_ERROR),
@ -112,7 +111,7 @@ describe('NodeDeleteDirective', () => {
}));
it('should raise info message on successful multiple files deletion', fakeAsync(done => {
spyOn(alfrescoApiService.nodesApi, 'deleteNode').and.returnValue(Promise.resolve(null));
spyOn(contentApi, 'deleteNode').and.returnValue(Observable.of(null));
actions$.pipe(
ofType<SnackbarInfoAction>(SNACKBAR_INFO),
@ -133,7 +132,7 @@ describe('NodeDeleteDirective', () => {
}));
it('should raise error message failed multiple files deletion', fakeAsync(done => {
spyOn(alfrescoApiService.nodesApi, 'deleteNode').and.returnValue(Promise.reject(null));
spyOn(contentApi, 'deleteNode').and.returnValue(Observable.throw(null));
actions$.pipe(
ofType<SnackbarErrorAction>(SNACKBAR_ERROR),
@ -154,11 +153,11 @@ describe('NodeDeleteDirective', () => {
}));
it('should raise warning message when only one file is successful', fakeAsync(done => {
spyOn(alfrescoApiService.nodesApi, 'deleteNode').and.callFake((id) => {
spyOn(contentApi, 'deleteNode').and.callFake((id) => {
if (id === '1') {
return Promise.reject(null);
return Observable.throw(null);
} else {
return Promise.resolve(null);
return Observable.of(null);
}
});
@ -181,17 +180,17 @@ describe('NodeDeleteDirective', () => {
}));
it('should raise warning message when some files are successfully deleted', fakeAsync(done => {
spyOn(alfrescoApiService.nodesApi, 'deleteNode').and.callFake((id) => {
spyOn(contentApi, 'deleteNode').and.callFake((id) => {
if (id === '1') {
return Promise.reject(null);
return Observable.throw(null);
}
if (id === '2') {
return Promise.resolve(null);
return Observable.of(null);
}
if (id === '3') {
return Promise.resolve(null);
return Observable.of(null);
}
});

View File

@ -27,7 +27,7 @@ import { Component, DebugElement } from '@angular/core';
import { ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Observable } from 'rxjs/Rx';
import { NodesApiService, NotificationService, TranslationService } from '@alfresco/adf-core';
import { NotificationService, TranslationService } from '@alfresco/adf-core';
import { NodeActionsService } from '../services/node-actions.service';
import { NodeMoveDirective } from './node-move.directive';
import { EffectsModule, Actions, ofType } from '@ngrx/effects';
@ -35,6 +35,7 @@ import { NodeEffects } from '../../store/effects/node.effects';
import { SnackbarErrorAction, SNACKBAR_ERROR } from '../../store/actions';
import { map } from 'rxjs/operators';
import { AppTestingModule } from '../../testing/app-testing.module';
import { ContentApiService } from '../../services/content-api.service';
@Component({
template: '<div [acaMoveNode]="selection"></div>'
@ -48,10 +49,10 @@ describe('NodeMoveDirective', () => {
let component: TestComponent;
let element: DebugElement;
let notificationService: NotificationService;
let nodesApiService: NodesApiService;
let service: NodeActionsService;
let actions$: Actions;
let translationService: TranslationService;
let contentApi: ContentApiService;
beforeEach(() => {
TestBed.configureTestingModule({
@ -65,6 +66,7 @@ describe('NodeMoveDirective', () => {
]
});
contentApi = TestBed.get(ContentApiService);
translationService = TestBed.get(TranslationService);
actions$ = TestBed.get(Actions);
@ -72,7 +74,6 @@ describe('NodeMoveDirective', () => {
component = fixture.componentInstance;
element = fixture.debugElement.query(By.directive(NodeMoveDirective));
notificationService = TestBed.get(NotificationService);
nodesApiService = TestBed.get(NodesApiService);
service = TestBed.get(NodeActionsService);
});
@ -382,7 +383,7 @@ describe('NodeMoveDirective', () => {
it('should restore deleted folder back to initial parent, after succeeded moving all its files', () => {
// when folder was deleted after all its children were moved to a folder with the same name from destination
spyOn(nodesApiService, 'restoreNode').and.returnValue(Observable.of(null));
spyOn(contentApi, 'restoreNode').and.returnValue(Observable.of(null));
const initialParent = 'parent-id-0';
const node = { entry: { id: 'folder-to-move-id', name: 'conflicting-name', parentId: initialParent, isFolder: true } };
@ -401,13 +402,13 @@ describe('NodeMoveDirective', () => {
element.triggerEventHandler('click', null);
service.contentMoved.next(<any>movedItems);
expect(nodesApiService.restoreNode).toHaveBeenCalled();
expect(contentApi.restoreNode).toHaveBeenCalled();
expect(notificationService.openSnackMessageAction)
.toHaveBeenCalledWith('APP.MESSAGES.INFO.NODE_MOVE.SINGULAR', 'APP.ACTIONS.UNDO', 10000);
});
it('should notify when error occurs on Undo Move action', fakeAsync(done => {
spyOn(nodesApiService, 'restoreNode').and.returnValue(Observable.throw(null));
spyOn(contentApi, 'restoreNode').and.returnValue(Observable.throw(null));
actions$.pipe(
ofType<SnackbarErrorAction>(SNACKBAR_ERROR),
@ -432,11 +433,11 @@ describe('NodeMoveDirective', () => {
element.triggerEventHandler('click', null);
service.contentMoved.next(<any>movedItems);
expect(nodesApiService.restoreNode).toHaveBeenCalled();
expect(contentApi.restoreNode).toHaveBeenCalled();
}));
it('should notify when some error of type Error occurs on Undo Move action', fakeAsync(done => {
spyOn(nodesApiService, 'restoreNode').and.returnValue(Observable.throw(new Error('oops!')));
spyOn(contentApi, 'restoreNode').and.returnValue(Observable.throw(new Error('oops!')));
actions$.pipe(
ofType<SnackbarErrorAction>(SNACKBAR_ERROR),
@ -460,11 +461,11 @@ describe('NodeMoveDirective', () => {
element.triggerEventHandler('click', null);
service.contentMoved.next(<any>movedItems);
expect(nodesApiService.restoreNode).toHaveBeenCalled();
expect(contentApi.restoreNode).toHaveBeenCalled();
}));
it('should notify permission error when it occurs on Undo Move action', fakeAsync(done => {
spyOn(nodesApiService, 'restoreNode').and.returnValue(Observable.throw(new Error(JSON.stringify({error: {statusCode: 403}}))));
spyOn(contentApi, 'restoreNode').and.returnValue(Observable.throw(new Error(JSON.stringify({error: {statusCode: 403}}))));
actions$.pipe(
ofType<SnackbarErrorAction>(SNACKBAR_ERROR),
@ -489,7 +490,7 @@ describe('NodeMoveDirective', () => {
service.contentMoved.next(<any>movedItems);
expect(service.moveNodes).toHaveBeenCalled();
expect(nodesApiService.restoreNode).toHaveBeenCalled();
expect(contentApi.restoreNode).toHaveBeenCalled();
}));
});

View File

@ -25,7 +25,7 @@
import { Directive, HostListener, Input } from '@angular/core';
import { TranslationService, NodesApiService, NotificationService } from '@alfresco/adf-core';
import { TranslationService, NotificationService } from '@alfresco/adf-core';
import { MinimalNodeEntity } from 'alfresco-js-api';
import { ContentManagementService } from '../services/content-management.service';
@ -34,6 +34,7 @@ import { Observable } from 'rxjs/Rx';
import { Store } from '@ngrx/store';
import { AppStore } from '../../store/states/app.state';
import { SnackbarErrorAction } from '../../store/actions';
import { ContentApiService } from '../../services/content-api.service';
@Directive({
selector: '[acaMoveNode]'
@ -51,10 +52,10 @@ export class NodeMoveDirective {
constructor(
private store: Store<AppStore>,
private contentApi: ContentApiService,
private content: ContentManagementService,
private notification: NotificationService,
private nodeActionsService: NodeActionsService,
private nodesApi: NodesApiService,
private translation: TranslationService
) {}
@ -173,7 +174,9 @@ export class NodeMoveDirective {
const restoreDeletedNodesBatch = this.nodeActionsService.moveDeletedEntries
.map((folderEntry) => {
return this.nodesApi.restoreNode(folderEntry.nodeId || folderEntry.id);
return this.contentApi
.restoreNode(folderEntry.nodeId || folderEntry.id)
.map(node => node.entry);
});
Observable.zip(...restoreDeletedNodesBatch, Observable.of(null))

View File

@ -27,7 +27,6 @@ import { Component, DebugElement } from '@angular/core';
import { TestBed, ComponentFixture, fakeAsync, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Observable } from 'rxjs/Rx';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { NodePermanentDeleteDirective } from './node-permanent-delete.directive';
import { MatDialog } from '@angular/material';
@ -39,6 +38,7 @@ import {
import { map } from 'rxjs/operators';
import { NodeEffects } from '../../store/effects/node.effects';
import { AppTestingModule } from '../../testing/app-testing.module';
import { ContentApiService } from '../../services/content-api.service';
@Component({
template: `<div [acaPermanentDelete]="selection"></div>`
@ -51,9 +51,9 @@ describe('NodePermanentDeleteDirective', () => {
let fixture: ComponentFixture<TestComponent>;
let element: DebugElement;
let component: TestComponent;
let alfrescoApiService: AlfrescoApiService;
let dialog: MatDialog;
let actions$: Actions;
let contentApi: ContentApiService;
beforeEach(() => {
TestBed.configureTestingModule({
@ -67,9 +67,7 @@ describe('NodePermanentDeleteDirective', () => {
]
});
alfrescoApiService = TestBed.get(AlfrescoApiService);
alfrescoApiService.reset();
contentApi = TestBed.get(ContentApiService);
actions$ = TestBed.get(Actions);
fixture = TestBed.createComponent(TestComponent);
@ -85,18 +83,18 @@ describe('NodePermanentDeleteDirective', () => {
});
it('does not purge nodes if no selection', () => {
spyOn(alfrescoApiService.nodesApi, 'purgeDeletedNode');
spyOn(contentApi, 'purgeDeletedNode');
component.selection = [];
fixture.detectChanges();
element.triggerEventHandler('click', null);
expect(alfrescoApiService.nodesApi.purgeDeletedNode).not.toHaveBeenCalled();
expect(contentApi.purgeDeletedNode).not.toHaveBeenCalled();
});
it('call purge nodes if selection is not empty', fakeAsync(() => {
spyOn(alfrescoApiService.nodesApi, 'purgeDeletedNode').and.returnValue(Promise.resolve());
spyOn(contentApi, 'purgeDeletedNode').and.returnValue(Observable.of({}));
component.selection = [ { entry: { id: '1' } } ];
@ -104,7 +102,7 @@ describe('NodePermanentDeleteDirective', () => {
element.triggerEventHandler('click', null);
tick();
expect(alfrescoApiService.nodesApi.purgeDeletedNode).toHaveBeenCalled();
expect(contentApi.purgeDeletedNode).toHaveBeenCalled();
}));
describe('notification', () => {
@ -116,17 +114,17 @@ describe('NodePermanentDeleteDirective', () => {
})
);
spyOn(alfrescoApiService.nodesApi, 'purgeDeletedNode').and.callFake((id) => {
spyOn(contentApi, 'purgeDeletedNode').and.callFake((id) => {
if (id === '1') {
return Promise.resolve();
return Observable.of({});
}
if (id === '2') {
return Promise.reject({});
return Observable.throw({});
}
if (id === '3') {
return Promise.reject({});
return Observable.throw({});
}
});
@ -149,21 +147,21 @@ describe('NodePermanentDeleteDirective', () => {
})
);
spyOn(alfrescoApiService.nodesApi, 'purgeDeletedNode').and.callFake((id) => {
spyOn(contentApi, 'purgeDeletedNode').and.callFake((id) => {
if (id === '1') {
return Promise.resolve();
return Observable.of({});
}
if (id === '2') {
return Promise.reject({});
return Observable.throw({});
}
if (id === '3') {
return Promise.reject({});
return Observable.throw({});
}
if (id === '4') {
return Promise.resolve();
return Observable.of({});
}
});
@ -187,7 +185,7 @@ describe('NodePermanentDeleteDirective', () => {
})
);
spyOn(alfrescoApiService.nodesApi, 'purgeDeletedNode').and.returnValue(Promise.resolve());
spyOn(contentApi, 'purgeDeletedNode').and.returnValue(Observable.of({}));
component.selection = [
{ entry: { id: '1', name: 'name1' } }
@ -206,7 +204,7 @@ describe('NodePermanentDeleteDirective', () => {
})
);
spyOn(alfrescoApiService.nodesApi, 'purgeDeletedNode').and.returnValue(Promise.reject({}));
spyOn(contentApi, 'purgeDeletedNode').and.returnValue(Observable.throw({}));
component.selection = [
{ entry: { id: '1', name: 'name1' } }
@ -224,13 +222,13 @@ describe('NodePermanentDeleteDirective', () => {
done();
})
);
spyOn(alfrescoApiService.nodesApi, 'purgeDeletedNode').and.callFake((id) => {
spyOn(contentApi, 'purgeDeletedNode').and.callFake((id) => {
if (id === '1') {
return Promise.resolve();
return Observable.of({});
}
if (id === '2') {
return Promise.resolve();
return Observable.of({});
}
});
@ -251,13 +249,13 @@ describe('NodePermanentDeleteDirective', () => {
done();
})
);
spyOn(alfrescoApiService.nodesApi, 'purgeDeletedNode').and.callFake((id) => {
spyOn(contentApi, 'purgeDeletedNode').and.callFake((id) => {
if (id === '1') {
return Promise.reject({});
return Observable.throw({});
}
if (id === '2') {
return Promise.reject({});
return Observable.throw({});
}
});

View File

@ -26,7 +26,6 @@
import { Component, DebugElement } from '@angular/core';
import { TestBed, ComponentFixture, fakeAsync, tick } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { NodeRestoreDirective } from './node-restore.directive';
import { ContentManagementService } from '../services/content-management.service';
import { Actions, ofType } from '@ngrx/effects';
@ -35,6 +34,8 @@ import { SnackbarErrorAction,
NavigateRouteAction, NAVIGATE_ROUTE } from '../../store/actions';
import { map } from 'rxjs/operators';
import { AppTestingModule } from '../../testing/app-testing.module';
import { ContentApiService } from '../../services/content-api.service';
import { Observable } from 'rxjs/Rx';
@Component({
template: `<div [acaRestoreNode]="selection"></div>`
@ -47,10 +48,10 @@ describe('NodeRestoreDirective', () => {
let fixture: ComponentFixture<TestComponent>;
let element: DebugElement;
let component: TestComponent;
let alfrescoService: AlfrescoApiService;
let directiveInstance: NodeRestoreDirective;
let contentManagementService: ContentManagementService;
let actions$: Actions;
let contentApi: ContentApiService;
beforeEach(() => {
TestBed.configureTestingModule({
@ -63,43 +64,41 @@ describe('NodeRestoreDirective', () => {
actions$ = TestBed.get(Actions);
alfrescoService = TestBed.get(AlfrescoApiService);
alfrescoService.reset();
fixture = TestBed.createComponent(TestComponent);
component = fixture.componentInstance;
element = fixture.debugElement.query(By.directive(NodeRestoreDirective));
directiveInstance = element.injector.get(NodeRestoreDirective);
contentManagementService = TestBed.get(ContentManagementService);
contentApi = TestBed.get(ContentApiService);
});
it('does not restore nodes if no selection', () => {
spyOn(alfrescoService.nodesApi, 'restoreNode');
spyOn(contentApi, 'restoreNode');
component.selection = [];
fixture.detectChanges();
element.triggerEventHandler('click', null);
expect(alfrescoService.nodesApi.restoreNode).not.toHaveBeenCalled();
expect(contentApi.restoreNode).not.toHaveBeenCalled();
});
it('does not restore nodes if selection has nodes without path', () => {
spyOn(alfrescoService.nodesApi, 'restoreNode');
spyOn(contentApi, 'restoreNode');
component.selection = [ { entry: { id: '1' } } ];
fixture.detectChanges();
element.triggerEventHandler('click', null);
expect(alfrescoService.nodesApi.restoreNode).not.toHaveBeenCalled();
expect(contentApi.restoreNode).not.toHaveBeenCalled();
});
it('call restore nodes if selection has nodes with path', fakeAsync(() => {
spyOn(directiveInstance, 'restoreNotification').and.callFake(() => null);
spyOn(alfrescoService.nodesApi, 'restoreNode').and.returnValue(Promise.resolve());
spyOn(alfrescoService.nodesApi, 'getDeletedNodes').and.returnValue(Promise.resolve({
spyOn(contentApi, 'restoreNode').and.returnValue(Observable.of({}));
spyOn(contentApi, 'getDeletedNodes').and.returnValue(Observable.of({
list: { entries: [] }
}));
@ -109,14 +108,14 @@ describe('NodeRestoreDirective', () => {
element.triggerEventHandler('click', null);
tick();
expect(alfrescoService.nodesApi.restoreNode).toHaveBeenCalled();
expect(contentApi.restoreNode).toHaveBeenCalled();
}));
describe('refresh()', () => {
it('dispatch event on finish', fakeAsync(done => {
spyOn(directiveInstance, 'restoreNotification').and.callFake(() => null);
spyOn(alfrescoService.nodesApi, 'restoreNode').and.returnValue(Promise.resolve());
spyOn(alfrescoService.nodesApi, 'getDeletedNodes').and.returnValue(Promise.resolve({
spyOn(contentApi, 'restoreNode').and.returnValue(Observable.of({}));
spyOn(contentApi, 'getDeletedNodes').and.returnValue(Observable.of({
list: { entries: [] }
}));
@ -132,7 +131,7 @@ describe('NodeRestoreDirective', () => {
describe('notification', () => {
beforeEach(() => {
spyOn(alfrescoService.nodesApi, 'getDeletedNodes').and.returnValue(Promise.resolve({
spyOn(contentApi, 'getDeletedNodes').and.returnValue(Observable.of({
list: { entries: [] }
}));
});
@ -145,17 +144,17 @@ describe('NodeRestoreDirective', () => {
map(action => done())
);
spyOn(alfrescoService.nodesApi, 'restoreNode').and.callFake((id) => {
spyOn(contentApi, 'restoreNode').and.callFake((id) => {
if (id === '1') {
return Promise.resolve();
return Observable.of({});
}
if (id === '2') {
return Promise.reject(error);
return Observable.throw(error);
}
if (id === '3') {
return Promise.reject(error);
return Observable.throw(error);
}
});
@ -172,7 +171,7 @@ describe('NodeRestoreDirective', () => {
it('should raise error message when restored node exist, error 409', fakeAsync(done => {
const error = { message: '{ "error": { "statusCode": 409 } }' };
spyOn(alfrescoService.nodesApi, 'restoreNode').and.returnValue(Promise.reject(error));
spyOn(contentApi, 'restoreNode').and.returnValue(Observable.throw(error));
actions$.pipe(
ofType<SnackbarErrorAction>(SNACKBAR_ERROR),
@ -191,7 +190,7 @@ describe('NodeRestoreDirective', () => {
it('should raise error message when restored node returns different statusCode', fakeAsync(done => {
const error = { message: '{ "error": { "statusCode": 404 } }' };
spyOn(alfrescoService.nodesApi, 'restoreNode').and.returnValue(Promise.reject(error));
spyOn(contentApi, 'restoreNode').and.returnValue(Observable.throw(error));
actions$.pipe(
ofType<SnackbarErrorAction>(SNACKBAR_ERROR),
@ -210,7 +209,7 @@ describe('NodeRestoreDirective', () => {
it('should raise error message when restored node location is missing', fakeAsync(done => {
const error = { message: '{ "error": { } }' };
spyOn(alfrescoService.nodesApi, 'restoreNode').and.returnValue(Promise.reject(error));
spyOn(contentApi, 'restoreNode').and.returnValue(Observable.throw(error));
actions$.pipe(
ofType<SnackbarErrorAction>(SNACKBAR_ERROR),
@ -227,13 +226,13 @@ describe('NodeRestoreDirective', () => {
}));
it('should raise info message when restore multiple nodes', fakeAsync(done => {
spyOn(alfrescoService.nodesApi, 'restoreNode').and.callFake((id) => {
spyOn(contentApi, 'restoreNode').and.callFake((id) => {
if (id === '1') {
return Promise.resolve();
return Observable.of({});
}
if (id === '2') {
return Promise.resolve();
return Observable.of({});
}
});
@ -253,7 +252,7 @@ describe('NodeRestoreDirective', () => {
}));
xit('should raise info message when restore selected node', fakeAsync(done => {
spyOn(alfrescoService.nodesApi, 'restoreNode').and.returnValue(Promise.resolve());
spyOn(contentApi, 'restoreNode').and.returnValue(Observable.of({}));
actions$.pipe(
ofType<SnackbarInfoAction>(SNACKBAR_INFO),
@ -270,7 +269,7 @@ describe('NodeRestoreDirective', () => {
}));
it('navigate to restore selected node location onAction', fakeAsync(done => {
spyOn(alfrescoService.nodesApi, 'restoreNode').and.returnValue(Promise.resolve());
spyOn(contentApi, 'restoreNode').and.returnValue(Observable.of({}));
actions$.pipe(
ofType<NavigateRouteAction>(NAVIGATE_ROUTE),

View File

@ -25,8 +25,6 @@
import { Directive, HostListener, Input } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { AlfrescoApiService } from '@alfresco/adf-core';
import {
MinimalNodeEntity,
MinimalNodeEntryEntity,
@ -44,6 +42,7 @@ import {
SnackbarInfoAction,
SnackbarUserAction
} from '../../store/actions';
import { ContentApiService } from '../../services/content-api.service';
@Directive({
selector: '[acaRestoreNode]'
@ -59,7 +58,7 @@ export class NodeRestoreDirective {
constructor(
private store: Store<AppStore>,
private alfrescoApiService: AlfrescoApiService,
private contentApi: ContentApiService,
private contentManagementService: ContentManagementService
) {}
@ -84,7 +83,7 @@ export class NodeRestoreDirective {
.do(restoredNodes => {
status = this.processStatus(restoredNodes);
})
.flatMap(() => this.getDeletedNodes())
.flatMap(() => this.contentApi.getDeletedNodes())
.subscribe((nodes: DeletedNodesPaging) => {
const selectedNodes = this.diff(status.fail, selection, false);
const remainingNodes = this.diff(
@ -101,20 +100,10 @@ export class NodeRestoreDirective {
});
}
private getDeletedNodes(): Observable<DeletedNodesPaging> {
return Observable.from(
this.alfrescoApiService.nodesApi.getDeletedNodes({
include: ['path']
})
);
}
private restoreNode(node: MinimalNodeEntity): Observable<any> {
const { entry } = node;
return Observable.from(
this.alfrescoApiService.nodesApi.restoreNode(entry.id)
)
return this.contentApi.restoreNode(entry.id)
.map(() => ({
status: 1,
entry

View File

@ -23,9 +23,10 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { Directive, HostListener, Input, ElementRef } from '@angular/core';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { Directive, HostListener, Input } from '@angular/core';
import { MinimalNodeEntity } from 'alfresco-js-api';
import { ContentManagementService } from '../services/content-management.service';
import { ContentApiService } from '../../services/content-api.service';
@Directive({
selector: '[acaUnshareNode]'
@ -37,8 +38,8 @@ export class NodeUnshareDirective {
selection: MinimalNodeEntity[];
constructor(
private apiService: AlfrescoApiService,
private el: ElementRef) {
private contentApi: ContentApiService,
private contentManagement: ContentManagementService) {
}
@HostListener('click')
@ -49,14 +50,8 @@ export class NodeUnshareDirective {
}
private async unshareLinks(links: MinimalNodeEntity[]) {
const promises = links.map(link => this.apiService.sharedLinksApi.deleteSharedLink(link.entry.id));
const promises = links.map(link => this.contentApi.deleteSharedLink(link.entry.id).toPromise());
await Promise.all(promises);
this.emitDone();
this.contentManagement.linksUnshared.next();
}
private emitDone() {
const e = new CustomEvent('links-unshared', { bubbles: true });
this.el.nativeElement.dispatchEvent(e);
}
}

View File

@ -24,15 +24,13 @@
*/
import { Directive, HostListener, Input } from '@angular/core';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { MinimalNodeEntity, MinimalNodeEntryEntity } from 'alfresco-js-api';
import { NodeVersionsDialogComponent } from '../../dialogs/node-versions/node-versions.dialog';
import { MatDialog } from '@angular/material';
import { Store } from '@ngrx/store';
import { AppStore } from '../../store/states/app.state';
import { SnackbarErrorAction } from '../../store/actions';
import { ContentApiService } from '../../services/content-api.service';
@Directive({
selector: '[acaNodeVersions]'
@ -48,7 +46,7 @@ export class NodeVersionsDirective {
constructor(
private store: Store<AppStore>,
private apiService: AlfrescoApiService,
private contentApi: ContentApiService,
private dialog: MatDialog
) {}
@ -57,10 +55,9 @@ export class NodeVersionsDirective {
let entry = this.node.entry;
if (entry.nodeId || (<any>entry).guid) {
entry = await this.apiService.nodesApi.getNodeInfo(
entry.nodeId || (<any>entry).id,
{ include: ['allowableOperations'] }
);
entry = await this.contentApi.getNodeInfo(
entry.nodeId || (<any>entry).id
).toPromise();
this.openVersionManagerDialog(entry);
} else {
this.openVersionManagerDialog(entry);

View File

@ -35,4 +35,5 @@ export class ContentManagementService {
folderEdited = new Subject<any>();
folderCreated = new Subject<any>();
siteDeleted = new Subject<string>();
linksUnshared = new Subject<any>();
}

View File

@ -24,21 +24,14 @@
*/
import { TestBed, async } from '@angular/core/testing';
import { MatDialog, MatDialogModule, MatIconModule } from '@angular/material';
import { OverlayModule } from '@angular/cdk/overlay';
import { MatDialog } from '@angular/material';
import { Observable } from 'rxjs/Rx';
import {
TranslationMock, AlfrescoApiService, NodesApiService,
TranslationService, ContentService, AuthenticationService,
UserPreferencesService, AppConfigService, StorageService,
CookieService, LogService, ThumbnailService
} from '@alfresco/adf-core';
import { AlfrescoApiService, TranslationService } from '@alfresco/adf-core';
import { DocumentListService } from '@alfresco/adf-content-services';
import { NodeActionsService } from './node-actions.service';
import { MinimalNodeEntryEntity } from 'alfresco-js-api';
import { TranslateModule } from '@ngx-translate/core';
import { HttpClientModule } from '@angular/common/http';
import { AppTestingModule } from '../../testing/app-testing.module';
import { ContentApiService } from '../../services/content-api.service';
class TestNode {
entry?: MinimalNodeEntryEntity;
@ -67,10 +60,10 @@ describe('NodeActionsService', () => {
const emptyChildrenList = {list: {entries: []}};
let service: NodeActionsService;
let apiService: AlfrescoApiService;
let nodesApiService: NodesApiService;
let nodesApi;
const spyOnSuccess = jasmine.createSpy('spyOnSuccess');
const spyOnError = jasmine.createSpy('spyOnError');
let contentApi: ContentApiService;
const helper = {
fakeCopyNode: (isForbidden: boolean = false, nameExistingOnDestination?: string) => {
@ -110,33 +103,16 @@ describe('NodeActionsService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
MatDialogModule,
MatIconModule,
HttpClientModule,
TranslateModule.forRoot(),
OverlayModule
],
providers: [
AlfrescoApiService,
NodesApiService,
{ provide: TranslationService, useClass: TranslationMock },
AuthenticationService,
UserPreferencesService,
AppConfigService,
CookieService,
LogService,
ThumbnailService,
StorageService,
ContentService,
DocumentListService,
NodeActionsService
AppTestingModule
]
});
contentApi = TestBed.get(ContentApiService);
service = TestBed.get(NodeActionsService);
apiService = TestBed.get(AlfrescoApiService);
apiService.reset();
nodesApiService = TestBed.get(NodesApiService);
nodesApi = apiService.getInstance().nodes;
});
@ -884,7 +860,7 @@ describe('NodeActionsService', () => {
beforeEach(() => {
parentFolderToMove = new TestNode('parent-folder', !isFile, 'conflicting-name');
spyOnDelete = spyOn(nodesApiService, 'deleteNode').and.returnValue(Observable.of(null));
spyOnDelete = spyOn(contentApi, 'deleteNode').and.returnValue(Observable.of(null));
});
afterEach(() => {

View File

@ -27,9 +27,10 @@ import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material';
import { Observable, Subject } from 'rxjs/Rx';
import { AlfrescoApiService, ContentService, NodesApiService, DataColumn, TranslationService } from '@alfresco/adf-core';
import { AlfrescoApiService, ContentService, DataColumn, TranslationService } from '@alfresco/adf-core';
import { DocumentListService, ContentNodeSelectorComponent, ContentNodeSelectorComponentData } from '@alfresco/adf-content-services';
import { MinimalNodeEntity, MinimalNodeEntryEntity, SitePaging } from 'alfresco-js-api';
import { ContentApiService } from '../../services/content-api.service';
@Injectable()
export class NodeActionsService {
@ -42,10 +43,10 @@ export class NodeActionsService {
isSitesDestinationAvailable = false;
constructor(private contentService: ContentService,
private contentApi: ContentApiService,
private dialog: MatDialog,
private documentListService: DocumentListService,
private apiService: AlfrescoApiService,
private nodesApi: NodesApiService,
private translation: TranslationService) {}
/**
@ -422,7 +423,7 @@ export class NodeActionsService {
// Check if there's nodeId for Shared Files
const nodeEntryId = nodeEntry.nodeId || nodeEntry.id;
// delete it from location
return this.nodesApi.deleteNode(nodeEntryId)
return this.contentApi.deleteNode(nodeEntryId)
.flatMap(() => {
this.moveDeletedEntries.push(nodeEntry);
return Observable.of(newContent);

View File

@ -26,31 +26,26 @@
import { Store } from '@ngrx/store';
import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
import { Person } from 'alfresco-js-api';
import { Observable } from 'rxjs/Observable';
import { AppStore } from '../../store/states/app.state';
import { SetUserAction } from '../../store/actions/user.actions';
import { selectUser } from '../../store/selectors/app.selectors';
import { PeopleContentService } from '@alfresco/adf-core';
import { ContentApiService } from '../../services/content-api.service';
@Injectable()
export class ProfileResolver implements Resolve<any> {
constructor(private store: Store<AppStore>, private peopleApi: PeopleContentService) { }
export class ProfileResolver implements Resolve<Person> {
constructor(
private store: Store<AppStore>,
private contentApi: ContentApiService
) {}
resolve(): Observable<any> {
this.init();
return this.profileLoaded();
}
profileLoaded(): Observable<any> {
return this.store.select(selectUser).take(1);
}
init(): void {
this.peopleApi.getCurrentPerson().subscribe((person: any) => {
this.store.dispatch(new SetUserAction(person.entry));
resolve(): Observable<Person> {
return new Observable(observer => {
this.contentApi.getPerson('-me-').subscribe(person => {
this.store.dispatch(new SetUserAction(person.entry));
observer.next(person.entry);
observer.complete();
});
});
}
}

View File

@ -1,9 +1,9 @@
<div class="inner-layout inner-layout--scroll">
<div class="inner-layout__content">
<div class="inner-layout__panel content--scroll">
<article *ngIf="ecmVersion" class="padding">
<article *ngIf="repository" class="padding">
<header class="header padding-left">Alfresco Content Services</header>
<p class="padding-left"> version: {{ ecmVersion.edition }} {{ ecmVersion.version.display }} </p>
<p class="padding-left"> version: {{ repository.edition }} {{ repository.version.display }} </p>
</article>
<article class="padding-top-bottom">

View File

@ -25,15 +25,16 @@
import { Component, OnInit } from '@angular/core';
import { Http } from '@angular/http';
import { DiscoveryApiService } from '@alfresco/adf-core';
import { EcmProductVersionModel, ObjectDataTableAdapter } from '@alfresco/adf-core';
import { ObjectDataTableAdapter } from '@alfresco/adf-core';
import { ContentApiService } from '../../services/content-api.service';
import { RepositoryInfo } from 'alfresco-js-api';
@Component({
selector: 'app-about',
templateUrl: './about.component.html'
})
export class AboutComponent implements OnInit {
ecmVersion: EcmProductVersionModel = null;
repository: RepositoryInfo;
data: ObjectDataTableAdapter;
status: ObjectDataTableAdapter;
license: ObjectDataTableAdapter;
@ -42,15 +43,17 @@ export class AboutComponent implements OnInit {
releaseVersion = '';
constructor(
private discovery: DiscoveryApiService,
private contentApi: ContentApiService,
private http: Http
) {}
ngOnInit() {
this.discovery.getEcmProductInfo().subscribe((ecmVers) => {
this.ecmVersion = ecmVers;
this.contentApi.getRepositoryInformation()
.map(node => node.entry.repository)
.subscribe(repository => {
this.repository = repository;
this.modules = new ObjectDataTableAdapter(this.ecmVersion.modules, [
this.modules = new ObjectDataTableAdapter(repository.modules, [
{type: 'text', key: 'id', title: 'ID', sortable: true},
{type: 'text', key: 'title', title: 'Title', sortable: true},
{type: 'text', key: 'version', title: 'Description', sortable: true},
@ -60,14 +63,14 @@ export class AboutComponent implements OnInit {
{type: 'text', key: 'versionMax', title: 'Version Max', sortable: true}
]);
this.status = new ObjectDataTableAdapter([this.ecmVersion.status], [
this.status = new ObjectDataTableAdapter([repository.status], [
{type: 'text', key: 'isReadOnly', title: 'Read Only', sortable: true},
{type: 'text', key: 'isAuditEnabled', title: 'Audit Enable', sortable: true},
{type: 'text', key: 'isQuickShareEnabled', title: 'Quick Shared Enable', sortable: true},
{type: 'text', key: 'isThumbnailGenerationEnabled', title: 'Thumbnail Generation', sortable: true}
]);
this.license = new ObjectDataTableAdapter([this.ecmVersion.license], [
this.license = new ObjectDataTableAdapter([repository.license], [
{type: 'date', key: 'issuedAt', title: 'Issued At', sortable: true},
{type: 'date', key: 'expiresAt', title: 'Expires At', sortable: true},
{type: 'text', key: 'remainingDays', title: 'Remaining Days', sortable: true},

View File

@ -28,7 +28,6 @@ import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Router } from '@angular/router';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import {
NodesApiService,
AlfrescoApiService,
TimeAgoPipe, NodeNameTooltipPipe,
NodeFavoriteDirective, DataTableComponent, AppConfigPipe
@ -38,13 +37,14 @@ import { ContentManagementService } from '../../common/services/content-manageme
import { FavoritesComponent } from './favorites.component';
import { AppTestingModule } from '../../testing/app-testing.module';
import { ContentApiService } from '../../services/content-api.service';
describe('FavoritesComponent', () => {
let fixture: ComponentFixture<FavoritesComponent>;
let component: FavoritesComponent;
let nodesApi: NodesApiService;
let alfrescoApi: AlfrescoApiService;
let contentService: ContentManagementService;
let contentApi: ContentApiService;
let router: Router;
let page;
let node;
@ -93,11 +93,12 @@ describe('FavoritesComponent', () => {
fixture = TestBed.createComponent(FavoritesComponent);
component = fixture.componentInstance;
nodesApi = TestBed.get(NodesApiService);
alfrescoApi = TestBed.get(AlfrescoApiService);
alfrescoApi.reset();
spyOn(alfrescoApi.favoritesApi, 'getFavorites').and.returnValue(Promise.resolve(page));
contentApi = TestBed.get(ContentApiService);
contentService = TestBed.get(ContentManagementService);
router = TestBed.get(Router);
});
@ -135,7 +136,7 @@ describe('FavoritesComponent', () => {
describe('Node navigation', () => {
beforeEach(() => {
spyOn(nodesApi, 'getNode').and.returnValue(Observable.of(node));
spyOn(contentApi, 'getNode').and.returnValue(Observable.of({ entry: node}));
spyOn(router, 'navigate');
fixture.detectChanges();
});

View File

@ -23,7 +23,6 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { NodesApiService } from '@alfresco/adf-core';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Store } from '@ngrx/store';
@ -37,6 +36,7 @@ import { ContentManagementService } from '../../common/services/content-manageme
import { NodePermissionService } from '../../common/services/node-permission.service';
import { AppStore } from '../../store/states/app.state';
import { PageComponent } from '../page.component';
import { ContentApiService } from '../../services/content-api.service';
@Component({
templateUrl: './favorites.component.html'
@ -45,7 +45,7 @@ export class FavoritesComponent extends PageComponent implements OnInit {
constructor(
private router: Router,
store: Store<AppStore>,
private nodesApi: NodesApiService,
private contentApi: ContentApiService,
private content: ContentManagementService,
public permission: NodePermissionService
) {
@ -74,8 +74,9 @@ export class FavoritesComponent extends PageComponent implements OnInit {
};
if (isFolder) {
this.nodesApi
this.contentApi
.getNode(id)
.map(node => node.entry)
.subscribe(({ path }: MinimalNodeEntryEntity) => {
const routeUrl = isSitePath(path)
? '/libraries'

View File

@ -28,7 +28,6 @@ import { TestBed, fakeAsync, tick, ComponentFixture } from '@angular/core/testin
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import {
NodesApiService,
TimeAgoPipe, NodeNameTooltipPipe, FileSizePipe, NodeFavoriteDirective,
DataTableComponent, UploadService, AppConfigPipe
} from '@alfresco/adf-core';
@ -38,6 +37,7 @@ import { BrowsingFilesService } from '../../common/services/browsing-files.servi
import { NodeActionsService } from '../../common/services/node-actions.service';
import { FilesComponent } from './files.component';
import { AppTestingModule } from '../../testing/app-testing.module';
import { ContentApiService } from '../../services/content-api.service';
describe('FilesComponent', () => {
let node;
@ -46,10 +46,10 @@ describe('FilesComponent', () => {
let component: FilesComponent;
let contentManagementService: ContentManagementService;
let uploadService: UploadService;
let nodesApi: NodesApiService;
let router: Router;
let browsingFilesService: BrowsingFilesService;
let nodeActionsService: NodeActionsService;
let contentApi: ContentApiService;
beforeAll(() => {
// testing only functional-wise not time-wise
@ -83,10 +83,10 @@ describe('FilesComponent', () => {
contentManagementService = TestBed.get(ContentManagementService);
uploadService = TestBed.get(UploadService);
nodesApi = TestBed.get(NodesApiService);
router = TestBed.get(Router);
browsingFilesService = TestBed.get(BrowsingFilesService);
nodeActionsService = TestBed.get(NodeActionsService);
contentApi = TestBed.get(ContentApiService);
});
beforeEach(() => {
@ -103,7 +103,7 @@ describe('FilesComponent', () => {
describe('Current page is valid', () => {
it('should be a valid current page', fakeAsync(() => {
spyOn(component, 'fetchNode').and.returnValue(Observable.of(node));
spyOn(contentApi, 'getNode').and.returnValue(Observable.of({ entry: node }));
spyOn(component, 'fetchNodes').and.returnValue(Observable.throw(null));
component.ngOnInit();
@ -114,7 +114,7 @@ describe('FilesComponent', () => {
}));
it('should set current page as invalid path', fakeAsync(() => {
spyOn(component, 'fetchNode').and.returnValue(Observable.of(node));
spyOn(contentApi, 'getNode').and.returnValue(Observable.of({ entry: node }));
spyOn(component, 'fetchNodes').and.returnValue(Observable.of(page));
component.ngOnInit();
@ -127,7 +127,7 @@ describe('FilesComponent', () => {
describe('OnInit', () => {
it('should set current node', () => {
spyOn(component, 'fetchNode').and.returnValue(Observable.of(node));
spyOn(contentApi, 'getNode').and.returnValue(Observable.of({ entry: node }));
spyOn(component, 'fetchNodes').and.returnValue(Observable.of(page));
fixture.detectChanges();
@ -136,7 +136,7 @@ describe('FilesComponent', () => {
});
it('should get current node children', () => {
spyOn(component, 'fetchNode').and.returnValue(Observable.of(node));
spyOn(contentApi, 'getNode').and.returnValue(Observable.of({ entry: node }));
spyOn(component, 'fetchNodes').and.returnValue(Observable.of(page));
fixture.detectChanges();
@ -145,7 +145,7 @@ describe('FilesComponent', () => {
});
it('emits onChangeParent event', () => {
spyOn(component, 'fetchNode').and.returnValue(Observable.of(node));
spyOn(contentApi, 'getNode').and.returnValue(Observable.of({ entry: node }));
spyOn(component, 'fetchNodes').and.returnValue(Observable.of(page));
spyOn(browsingFilesService.onChangeParent, 'next').and.callFake((val) => val);
@ -158,7 +158,7 @@ describe('FilesComponent', () => {
it('if should navigate to parent if node is not a folder', () => {
node.isFolder = false;
node.parentId = 'parent-id';
spyOn(component, 'fetchNode').and.returnValue(Observable.of(node));
spyOn(contentApi, 'getNode').and.returnValue(Observable.of({ entry: node }));
spyOn(router, 'navigate');
fixture.detectChanges();
@ -169,7 +169,7 @@ describe('FilesComponent', () => {
describe('refresh on events', () => {
beforeEach(() => {
spyOn(component, 'fetchNode').and.returnValue(Observable.of(node));
spyOn(contentApi, 'getNode').and.returnValue(Observable.of(node));
spyOn(component, 'fetchNodes').and.returnValue(Observable.of(page));
spyOn(component.documentList, 'reload');
@ -269,25 +269,10 @@ describe('FilesComponent', () => {
});
});
describe('fetchNode()', () => {
beforeEach(() => {
spyOn(component, 'fetchNodes').and.returnValue(Observable.of(page));
spyOn(nodesApi, 'getNode').and.returnValue(Observable.of(node));
fixture.detectChanges();
});
it('should call getNode api with node id', () => {
component.fetchNode('nodeId');
expect(nodesApi.getNode).toHaveBeenCalledWith('nodeId');
});
});
describe('fetchNodes()', () => {
beforeEach(() => {
spyOn(component, 'fetchNode').and.returnValue(Observable.of(node));
spyOn(nodesApi, 'getNodeChildren').and.returnValue(Observable.of(page));
spyOn(contentApi, 'getNode').and.returnValue(Observable.of(node));
spyOn(contentApi, 'getNodeChildren').and.returnValue(Observable.of(page));
fixture.detectChanges();
});
@ -295,13 +280,13 @@ describe('FilesComponent', () => {
it('should call getNode api with node id', () => {
component.fetchNodes('nodeId');
expect(nodesApi.getNodeChildren).toHaveBeenCalledWith('nodeId', jasmine.any(Object));
expect(contentApi.getNodeChildren).toHaveBeenCalledWith('nodeId');
});
});
describe('onBreadcrumbNavigate()', () => {
beforeEach(() => {
spyOn(component, 'fetchNode').and.returnValue(Observable.of(node));
spyOn(contentApi, 'getNode').and.returnValue(Observable.of(node));
spyOn(component, 'fetchNodes').and.returnValue(Observable.of(page));
fixture.detectChanges();
@ -319,7 +304,7 @@ describe('FilesComponent', () => {
describe('Node navigation', () => {
beforeEach(() => {
spyOn(component, 'fetchNode').and.returnValue(Observable.of(node));
spyOn(contentApi, 'getNode').and.returnValue(Observable.of(node));
spyOn(component, 'fetchNodes').and.returnValue(Observable.of(page));
spyOn(router, 'navigate');

View File

@ -23,7 +23,7 @@
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { AlfrescoApiService, FileUploadEvent, NodesApiService, UploadService } from '@alfresco/adf-core';
import { FileUploadEvent, UploadService } from '@alfresco/adf-core';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute, Params, Router } from '@angular/router';
import { Store } from '@ngrx/store';
@ -35,6 +35,7 @@ import { NodeActionsService } from '../../common/services/node-actions.service';
import { NodePermissionService } from '../../common/services/node-permission.service';
import { AppStore } from '../../store/states/app.state';
import { PageComponent } from '../page.component';
import { ContentApiService } from '../../services/content-api.service';
@Component({
templateUrl: './files.component.html'
@ -47,13 +48,12 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
constructor(private router: Router,
private route: ActivatedRoute,
private contentApi: ContentApiService,
store: Store<AppStore>,
private nodesApi: NodesApiService,
private nodeActionsService: NodeActionsService,
private uploadService: UploadService,
private contentManagementService: ContentManagementService,
private browsingFilesService: BrowsingFilesService,
private apiService: AlfrescoApiService,
public permission: NodePermissionService) {
super(store);
}
@ -69,8 +69,9 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
route.params.subscribe(({ folderId }: Params) => {
const nodeId = folderId || data.defaultNodeId;
this.fetchNode(nodeId)
.do((node) => {
this.contentApi.getNode(nodeId)
.map(node => node.entry)
.do(node => {
if (node.isFolder) {
this.updateCurrentNode(node);
} else {
@ -78,14 +79,10 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
}
})
.skipWhile(node => !node.isFolder)
.flatMap((node) => this.fetchNodes(node.id))
.flatMap(node => this.fetchNodes(node.id))
.subscribe(
(page) => {
this.isValidPath = true;
},
error => {
this.isValidPath = false;
}
() => this.isValidPath = true,
() => this.isValidPath = false
);
});
@ -107,18 +104,8 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
this.browsingFilesService.onChangeParent.next(null);
}
fetchNode(nodeId: string): Observable<MinimalNodeEntryEntity> {
return this.nodesApi.getNode(nodeId);
}
fetchNodes(parentNodeId?: string, options: { maxItems?: number, skipCount?: number } = {}): Observable<NodePaging> {
const defaults = {
include: [ 'isLocked', 'path', 'properties', 'allowableOperations' ]
};
const queryOptions = Object.assign({}, defaults, options);
return this.nodesApi.getNodeChildren(parentNodeId, queryOptions);
fetchNodes(parentNodeId?: string): Observable<NodePaging> {
return this.contentApi.getNodeChildren(parentNodeId);
}
navigate(nodeId: string = null) {
@ -246,7 +233,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
if (this.isSiteContainer(node)) {
// rename 'documentLibrary' entry to the target site display name
// clicking on the breadcrumb entry loads the site content
const parentNode = await this.apiService.nodesApi.getNodeInfo(node.parentId);
const parentNode = await this.contentApi.getNodeInfo(node.parentId).toPromise();
node.name = parentNode.properties['cm:title'] || parentNode.name;
// remove the site entry
@ -256,7 +243,7 @@ export class FilesComponent extends PageComponent implements OnInit, OnDestroy {
const docLib = elements.findIndex(el => el.name === 'documentLibrary');
if (docLib > -1) {
const siteFragment = elements[docLib - 1];
const siteNode = await this.apiService.nodesApi.getNodeInfo(siteFragment.id);
const siteNode = await this.contentApi.getNodeInfo(siteFragment.id).toPromise();
// apply Site Name to the parent fragment
siteFragment.name = siteNode.properties['cm:title'] || siteNode.name;

View File

@ -26,7 +26,7 @@
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { MinimalNodeEntity, MinimalNodeEntryEntity } from 'alfresco-js-api';
import { NodePermissionService } from '../../common/services/node-permission.service';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { ContentApiService } from '../../services/content-api.service';
@Component({
selector: 'aca-info-drawer',
@ -67,7 +67,7 @@ export class InfoDrawerComponent implements OnChanges {
constructor(
public permission: NodePermissionService,
private apiService: AlfrescoApiService
private contentApi: ContentApiService
) {}
ngOnChanges(changes: SimpleChanges) {
@ -88,15 +88,13 @@ export class InfoDrawerComponent implements OnChanges {
if (nodeId) {
this.isLoading = true;
this.apiService.nodesApi
.getNodeInfo(nodeId, { include: ['allowableOperations'] })
.then((entity: MinimalNodeEntryEntity) => {
this.contentApi.getNodeInfo(nodeId).subscribe(
entity => {
this.displayNode = entity;
this.isLoading = false;
})
.catch(() => {
this.isLoading = false;
});
},
() => this.isLoading = false
);
}
}
}

View File

@ -28,7 +28,7 @@ import { Observable } from 'rxjs/Rx';
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Router } from '@angular/router';
import {
NodesApiService, AlfrescoApiService,
AlfrescoApiService,
TimeAgoPipe, NodeNameTooltipPipe, NodeFavoriteDirective, DataTableComponent, AppConfigPipe
} from '@alfresco/adf-core';
import { DocumentListComponent } from '@alfresco/adf-content-services';
@ -36,11 +36,12 @@ import { ShareDataTableAdapter } from '@alfresco/adf-content-services';
import { LibrariesComponent } from './libraries.component';
import { ExperimentalDirective } from '../../directives/experimental.directive';
import { AppTestingModule } from '../../testing/app-testing.module';
import { ContentApiService } from '../../services/content-api.service';
describe('LibrariesComponent', () => {
let fixture: ComponentFixture<LibrariesComponent>;
let component: LibrariesComponent;
let nodesApi: NodesApiService;
let contentApi: ContentApiService;
let alfrescoApi: AlfrescoApiService;
let router: Router;
let page;
@ -81,13 +82,14 @@ describe('LibrariesComponent', () => {
fixture = TestBed.createComponent(LibrariesComponent);
component = fixture.componentInstance;
nodesApi = TestBed.get(NodesApiService);
alfrescoApi = TestBed.get(AlfrescoApiService);
alfrescoApi.reset();
router = TestBed.get(Router);
spyOn(alfrescoApi.sitesApi, 'getSites').and.returnValue((Promise.resolve(page)));
spyOn(alfrescoApi.peopleApi, 'getSiteMembership').and.returnValue((Promise.resolve({})));
contentApi = TestBed.get(ContentApiService);
});
describe('makeLibraryTooltip()', () => {
@ -153,7 +155,7 @@ describe('LibrariesComponent', () => {
it('navigates to node id', () => {
const document = { id: 'documentId' };
spyOn(nodesApi, 'getNode').and.returnValue(Observable.of(document));
spyOn(contentApi, 'getNode').and.returnValue(Observable.of({ entry: document }));
component.navigate(node.id);

View File

@ -25,7 +25,6 @@
import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { NodesApiService } from '@alfresco/adf-core';
import { ShareDataRow } from '@alfresco/adf-content-services';
import { PageComponent } from '../page.component';
@ -34,15 +33,16 @@ import { AppStore } from '../../store/states/app.state';
import { DeleteLibraryAction } from '../../store/actions';
import { SiteEntry } from 'alfresco-js-api';
import { ContentManagementService } from '../../common/services/content-management.service';
import { ContentApiService } from '../../services/content-api.service';
@Component({
templateUrl: './libraries.component.html'
})
export class LibrariesComponent extends PageComponent implements OnInit {
constructor(private nodesApi: NodesApiService,
private route: ActivatedRoute,
constructor(private route: ActivatedRoute,
private content: ContentManagementService,
private contentApi: ContentApiService,
store: Store<AppStore>,
private router: Router) {
super(store);
@ -89,8 +89,9 @@ export class LibrariesComponent extends PageComponent implements OnInit {
navigate(libraryId: string) {
if (libraryId) {
this.nodesApi
this.contentApi
.getNode(libraryId, { relativePath: '/documentLibrary' })
.map(node => node.entry)
.subscribe(documentLibrary => {
this.router.navigate([ './', documentLibrary.id ], { relativeTo: this.route });
});

View File

@ -24,13 +24,14 @@
*/
import { Component, Input, ChangeDetectionStrategy, OnInit, ViewEncapsulation } from '@angular/core';
import { AlfrescoApiService, DataColumn, DataRow, DataTableAdapter } from '@alfresco/adf-core';
import { DataColumn, DataRow, DataTableAdapter } from '@alfresco/adf-core';
import { PathInfoEntity, MinimalNodeEntity } from 'alfresco-js-api';
import { Observable } from 'rxjs/Rx';
import { Store } from '@ngrx/store';
import { AppStore } from '../../store/states/app.state';
import { NavigateToParentFolder } from '../../store/actions';
import { ContentApiService } from '../../services/content-api.service';
@Component({
selector: 'app-location-link',
@ -59,7 +60,7 @@ export class LocationLinkComponent implements OnInit {
constructor(
private store: Store<AppStore>,
private apiService: AlfrescoApiService) {
private contentApi: ContentApiService) {
}
goToLocation() {
@ -104,12 +105,12 @@ export class LocationLinkComponent implements OnInit {
const fragment = path.elements[path.elements.length - 2];
return new Observable<string>(observer => {
this.apiService.nodesApi.getNodeInfo(fragment.id).then(
(node) => {
this.contentApi.getNodeInfo(fragment.id).subscribe(
node => {
observer.next(node.properties['cm:title'] || node.name || fragment.name);
observer.complete();
},
(err) => {
() => {
observer.next(fragment.name);
observer.complete();
}
@ -132,8 +133,8 @@ export class LocationLinkComponent implements OnInit {
const fragment = elements[2];
return new Observable<string>(observer => {
this.apiService.nodesApi.getNodeInfo(fragment.id).then(
(node) => {
this.contentApi.getNodeInfo(fragment.id).subscribe(
node => {
elements.splice(0, 2);
elements[0].name = node.properties['cm:title'] || node.name || fragment.name;
elements.splice(1, 1);
@ -142,7 +143,7 @@ export class LocationLinkComponent implements OnInit {
observer.next(elements.map(e => e.name).join('/'));
observer.complete();
},
(err) => {
() => {
elements.splice(0, 2);
elements.unshift({ id: null, name: 'File Libraries' });
elements.splice(2, 1);

View File

@ -25,13 +25,14 @@
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { TestBed, async, ComponentFixture } from '@angular/core/testing';
import { AlfrescoApiService, UserPreferencesService, AppConfigPipe, NodeFavoriteDirective } from '@alfresco/adf-core';
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { UserPreferencesService, AppConfigPipe, NodeFavoriteDirective } from '@alfresco/adf-core';
import { PreviewComponent } from './preview.component';
import { Observable } from 'rxjs/Rx';
import { EffectsModule } from '@ngrx/effects';
import { NodeEffects } from '../../store/effects/node.effects';
import { AppTestingModule } from '../../testing/app-testing.module';
import { ContentApiService } from '../../services/content-api.service';
describe('PreviewComponent', () => {
@ -39,10 +40,10 @@ describe('PreviewComponent', () => {
let component: PreviewComponent;
let router: Router;
let route: ActivatedRoute;
let alfrescoApi: AlfrescoApiService;
let preferences: UserPreferencesService;
let contentApi: ContentApiService;
beforeEach(async(() => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
AppTestingModule,
@ -54,18 +55,16 @@ describe('PreviewComponent', () => {
NodeFavoriteDirective
],
schemas: [ NO_ERRORS_SCHEMA ]
})
.compileComponents().then(() => {
fixture = TestBed.createComponent(PreviewComponent);
component = fixture.componentInstance;
router = TestBed.get(Router);
route = TestBed.get(ActivatedRoute);
alfrescoApi = TestBed.get(AlfrescoApiService);
alfrescoApi.reset();
preferences = TestBed.get(UserPreferencesService);
});
}));
fixture = TestBed.createComponent(PreviewComponent);
component = fixture.componentInstance;
router = TestBed.get(Router);
route = TestBed.get(ActivatedRoute);
preferences = TestBed.get(UserPreferencesService);
contentApi = TestBed.get(ContentApiService);
});
it('should extract the property path root', () => {
expect(component.getRootField('some.property.path')).toBe('some');
@ -339,35 +338,33 @@ describe('PreviewComponent', () => {
it('should not display node when id is missing', async () => {
spyOn(router, 'navigate').and.stub();
spyOn(alfrescoApi.nodesApi, 'getNodeInfo').and.returnValue(
Promise.resolve(null)
spyOn(contentApi, 'getNodeInfo').and.returnValue(
Observable.of(null)
);
await component.displayNode(null);
expect(alfrescoApi.nodesApi.getNodeInfo).not.toHaveBeenCalled();
expect(contentApi.getNodeInfo).not.toHaveBeenCalled();
expect(router.navigate).not.toHaveBeenCalled();
});
it('should navigate to original location if node not found', async () => {
spyOn(router, 'navigate').and.stub();
spyOn(alfrescoApi.nodesApi, 'getNodeInfo').and.returnValue(
Promise.resolve(null)
spyOn(contentApi, 'getNodeInfo').and.returnValue(
Observable.of(null)
);
component.previewLocation = 'personal-files';
await component.displayNode('folder1');
expect(alfrescoApi.nodesApi.getNodeInfo).toHaveBeenCalledWith(
'folder1', { include: [ 'allowableOperations' ] }
);
expect(contentApi.getNodeInfo).toHaveBeenCalledWith('folder1');
expect(router.navigate).toHaveBeenCalledWith(['personal-files', 'folder1']);
});
it('should navigate to original location if node is not a File', async () => {
spyOn(router, 'navigate').and.stub();
spyOn(alfrescoApi.nodesApi, 'getNodeInfo').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'getNodeInfo').and.returnValue(
Observable.of({
isFile: false
})
);
@ -375,31 +372,27 @@ describe('PreviewComponent', () => {
component.previewLocation = 'personal-files';
await component.displayNode('folder1');
expect(alfrescoApi.nodesApi.getNodeInfo).toHaveBeenCalledWith(
'folder1', { include: [ 'allowableOperations' ] }
);
expect(contentApi.getNodeInfo).toHaveBeenCalledWith('folder1');
expect(router.navigate).toHaveBeenCalledWith(['personal-files', 'folder1']);
});
it('should navigate to original location in case of Alfresco API errors', async () => {
spyOn(router, 'navigate').and.stub();
spyOn(alfrescoApi.nodesApi, 'getNodeInfo').and.returnValue(
Promise.reject('error')
spyOn(contentApi, 'getNodeInfo').and.returnValue(
Observable.throw('error')
);
component.previewLocation = 'personal-files';
await component.displayNode('folder1');
expect(alfrescoApi.nodesApi.getNodeInfo).toHaveBeenCalledWith(
'folder1', { include: [ 'allowableOperations' ] }
);
expect(contentApi.getNodeInfo).toHaveBeenCalledWith('folder1');
expect(router.navigate).toHaveBeenCalledWith(['personal-files', 'folder1']);
});
it('should navigate to original location in case of internal errors', async () => {
spyOn(router, 'navigate').and.stub();
spyOn(alfrescoApi.nodesApi, 'getNodeInfo').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'getNodeInfo').and.returnValue(
Observable.of({
isFile: true
})
);
@ -410,17 +403,15 @@ describe('PreviewComponent', () => {
component.previewLocation = 'personal-files';
await component.displayNode('folder1');
expect(alfrescoApi.nodesApi.getNodeInfo).toHaveBeenCalledWith(
'folder1', { include: [ 'allowableOperations' ] }
);
expect(contentApi.getNodeInfo).toHaveBeenCalledWith('folder1');
expect(router.navigate).toHaveBeenCalledWith(['personal-files', 'folder1']);
});
it('should setup node for displaying', async () => {
spyOn(router, 'navigate').and.stub();
spyOn(component, 'getNearestNodes').and.returnValue({ left: 'node1', right: 'node3' });
spyOn(alfrescoApi.nodesApi, 'getNodeInfo').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'getNodeInfo').and.returnValue(
Observable.of({
id: 'node2',
parentId: 'parent1',
isFile: true
@ -439,8 +430,8 @@ describe('PreviewComponent', () => {
preferences.set('personal-files.sorting.key', 'name');
preferences.set('personal-files.sorting.direction', 'desc');
spyOn(alfrescoApi.nodesApi, 'getNodeChildren').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'getNodeChildren').and.returnValue(
Observable.of({
list: {
entries: [
{ entry: { id: 'node1', name: 'node 1' } },
@ -458,8 +449,8 @@ describe('PreviewComponent', () => {
preferences.set('personal-files.sorting.key', 'missing');
preferences.set('personal-files.sorting.direction', 'desc');
spyOn(alfrescoApi.nodesApi, 'getNodeChildren').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'getNodeChildren').and.returnValue(
Observable.of({
list: {
entries: [
{ entry: { id: 'node1', name: 'node 1' } },
@ -481,8 +472,8 @@ describe('PreviewComponent', () => {
it('should sort file ids for personal-files with [modifiedAt desc]', async () => {
spyOn(preferences, 'get').and.returnValue(null);
spyOn(alfrescoApi.nodesApi, 'getNodeChildren').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'getNodeChildren').and.returnValue(
Observable.of({
list: {
entries: [
{ entry: { id: 'node1', name: 'node 1', modifiedAt: 1 } },
@ -500,8 +491,8 @@ describe('PreviewComponent', () => {
preferences.set('personal-files.sorting.key', 'name');
preferences.set('personal-files.sorting.direction', 'desc');
spyOn(alfrescoApi.nodesApi, 'getNodeChildren').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'getNodeChildren').and.returnValue(
Observable.of({
list: {
entries: [
{ entry: { id: 'node1', name: 'node 1' } },
@ -523,8 +514,8 @@ describe('PreviewComponent', () => {
it('should sort file ids for libraries with [modifiedAt desc]', async () => {
spyOn(preferences, 'get').and.returnValue(null);
spyOn(alfrescoApi.nodesApi, 'getNodeChildren').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'getNodeChildren').and.returnValue(
Observable.of({
list: {
entries: [
{ entry: { id: 'node1', name: 'node 1', modifiedAt: new Date(1) } },
@ -542,8 +533,8 @@ describe('PreviewComponent', () => {
preferences.set('favorites.sorting.key', 'name');
preferences.set('favorites.sorting.direction', 'desc');
spyOn(alfrescoApi.favoritesApi, 'getFavorites').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'getFavorites').and.returnValue(
Observable.of({
list: {
entries: [
{ entry: { target: { file: { id: 'file3', name: 'file 3' } } } },
@ -561,8 +552,8 @@ describe('PreviewComponent', () => {
it('should sort file ids for favorites with [modifiedAt desc]', async () => {
spyOn(preferences, 'get').and.returnValue(null);
spyOn(alfrescoApi.favoritesApi, 'getFavorites').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'getFavorites').and.returnValue(
Observable.of({
list: {
entries: [
{ entry: { target: { file: { id: 'file3', modifiedAt: new Date(3) } } } },
@ -581,8 +572,8 @@ describe('PreviewComponent', () => {
preferences.set('shared.sorting.key', 'name');
preferences.set('shared.sorting.direction', 'asc');
spyOn(alfrescoApi.sharedLinksApi, 'findSharedLinks').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'findSharedLinks').and.returnValue(
Observable.of({
list: {
entries: [
{ entry: { nodeId: 'node2', name: 'node 2', modifiedAt: new Date(2) } },
@ -599,8 +590,8 @@ describe('PreviewComponent', () => {
it('should sort file ids for favorites with [modifiedAt desc]', async () => {
spyOn(preferences, 'get').and.returnValue(null);
spyOn(alfrescoApi.sharedLinksApi, 'findSharedLinks').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'findSharedLinks').and.returnValue(
Observable.of({
list: {
entries: [
{ entry: { nodeId: 'node2', name: 'node 2', modifiedAt: new Date(2) } },
@ -618,14 +609,14 @@ describe('PreviewComponent', () => {
preferences.set('recent-files.sorting.key', 'name');
preferences.set('recent-files.sorting.direction', 'asc');
spyOn(alfrescoApi.peopleApi, 'getPerson').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'getPerson').and.returnValue(
Observable.of({
entry: { id: 'user' }
})
);
spyOn(alfrescoApi.searchApi, 'search').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'search').and.returnValue(
Observable.of({
list: {
entries: [
{ entry: { id: 'node2', name: 'node 2', modifiedAt: new Date(2) } },
@ -642,14 +633,14 @@ describe('PreviewComponent', () => {
it('should sort file ids for favorites with [modifiedAt desc]', async () => {
spyOn(preferences, 'get').and.returnValue(null);
spyOn(alfrescoApi.peopleApi, 'getPerson').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'getPerson').and.returnValue(
Observable.of({
entry: { id: 'user' }
})
);
spyOn(alfrescoApi.searchApi, 'search').and.returnValue(
Promise.resolve({
spyOn(contentApi, 'search').and.returnValue(
Observable.of({
list: {
entries: [
{ entry: { id: 'node2', name: 'node 2', modifiedAt: new Date(2) } },

View File

@ -25,13 +25,14 @@
import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, Router, UrlTree, UrlSegmentGroup, UrlSegment, PRIMARY_OUTLET } from '@angular/router';
import { AlfrescoApiService, UserPreferencesService, ObjectUtils, UploadService } from '@alfresco/adf-core';
import { UserPreferencesService, ObjectUtils, UploadService } from '@alfresco/adf-core';
import { Node, MinimalNodeEntity } from 'alfresco-js-api';
import { NodePermissionService } from '../../common/services/node-permission.service';
import { Store } from '@ngrx/store';
import { AppStore } from '../../store/states/app.state';
import { DeleteNodesAction } from '../../store/actions';
import { PageComponent } from '../page.component';
import { ContentApiService } from '../../services/content-api.service';
@Component({
selector: 'app-preview',
templateUrl: 'preview.component.html',
@ -56,8 +57,8 @@ export class PreviewComponent extends PageComponent implements OnInit {
selectedEntities: MinimalNodeEntity[] = [];
constructor(
private contentApi: ContentApiService,
private uploadService: UploadService,
private apiService: AlfrescoApiService,
private preferences: UserPreferencesService,
private route: ActivatedRoute,
private router: Router,
@ -105,9 +106,7 @@ export class PreviewComponent extends PageComponent implements OnInit {
async displayNode(id: string) {
if (id) {
try {
this.node = await this.apiService.nodesApi.getNodeInfo(id, {
include: ['allowableOperations']
});
this.node = await this.contentApi.getNodeInfo(id).toPromise();
this.selectedEntities = [{ entry: this.node }];
if (this.node && this.node.isFile) {
@ -222,11 +221,11 @@ export class PreviewComponent extends PageComponent implements OnInit {
if ((source === 'personal-files' || source === 'libraries') && folderId) {
const sortKey = this.preferences.get('personal-files.sorting.key') || 'modifiedAt';
const sortDirection = this.preferences.get('personal-files.sorting.direction') || 'desc';
const nodes = await this.apiService.nodesApi.getNodeChildren(folderId, {
const nodes = await this.contentApi.getNodeChildren(folderId, {
// orderBy: `${sortKey} ${sortDirection}`,
fields: ['id', this.getRootField(sortKey)],
where: '(isFile=true)'
});
}).toPromise();
const entries = nodes.list.entries.map(obj => obj.entry);
this.sort(entries, sortKey, sortDirection);
@ -235,10 +234,10 @@ export class PreviewComponent extends PageComponent implements OnInit {
}
if (source === 'favorites') {
const nodes = await this.apiService.favoritesApi.getFavorites('-me-', {
const nodes = await this.contentApi.getFavorites('-me-', {
where: '(EXISTS(target/file))',
fields: ['target']
});
}).toPromise();
const sortKey = this.preferences.get('favorites.sorting.key') || 'modifiedAt';
const sortDirection = this.preferences.get('favorites.sorting.direction') || 'desc';
@ -252,9 +251,9 @@ export class PreviewComponent extends PageComponent implements OnInit {
const sortingKey = this.preferences.get('shared.sorting.key') || 'modifiedAt';
const sortingDirection = this.preferences.get('shared.sorting.direction') || 'desc';
const nodes = await this.apiService.sharedLinksApi.findSharedLinks({
const nodes = await this.contentApi.findSharedLinks({
fields: ['nodeId', this.getRootField(sortingKey)]
});
}).toPromise();
const entries = nodes.list.entries.map(obj => obj.entry);
this.sort(entries, sortingKey, sortingDirection);
@ -263,12 +262,12 @@ export class PreviewComponent extends PageComponent implements OnInit {
}
if (source === 'recent-files') {
const person = await this.apiService.peopleApi.getPerson('-me-');
const person = await this.contentApi.getPerson('-me-').toPromise();
const username = person.entry.id;
const sortingKey = this.preferences.get('recent-files.sorting.key') || 'modifiedAt';
const sortingDirection = this.preferences.get('recent-files.sorting.direction') || 'desc';
const nodes = await this.apiService.searchApi.search({
const nodes = await this.contentApi.search({
query: {
query: '*',
language: 'afts'
@ -284,7 +283,7 @@ export class PreviewComponent extends PageComponent implements OnInit {
field: 'cm:modified',
ascending: false
}]
});
}).toPromise();
const entries = nodes.list.entries.map(obj => obj.entry);
this.sort(entries, sortingKey, sortingDirection);

View File

@ -65,8 +65,7 @@
<button
mat-menu-item
*ngIf="permission.check(selection.nodes, ['delete'])"
[acaUnshareNode]="selection.nodes"
(links-unshared)="reload()">
[acaUnshareNode]="selection.nodes">
<mat-icon>stop_screen_share</mat-icon>
<span>{{ 'APP.ACTIONS.UNSHARE' | translate }}</span>
</button>

View File

@ -51,6 +51,7 @@ export class SharedFilesComponent extends PageComponent implements OnInit {
this.content.nodesDeleted.subscribe(() => this.reload()),
this.content.nodesMoved.subscribe(() => this.reload()),
this.content.nodesRestored.subscribe(() => this.reload()),
this.content.linksUnshared.subscribe(() => this.reload()),
this.uploadService.fileUploadError.subscribe((error) => this.onFileUploadedError(error))
]);
}

View File

@ -0,0 +1,229 @@
/*!
* @license
* Alfresco Example Content Application
*
* Copyright (C) 2005 - 2018 Alfresco Software Limited
*
* This file is part of the Alfresco Example Content Application.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* The Alfresco Example Content Application is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Alfresco Example Content Application is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
import { Injectable } from '@angular/core';
import { AlfrescoApiService, UserPreferencesService } from '@alfresco/adf-core';
import { Observable } from 'rxjs/Observable';
import {
MinimalNodeEntity,
NodePaging,
Node,
DeletedNodesPaging,
PersonEntry,
NodeEntry,
DiscoveryEntry,
FavoritePaging,
SharedLinkPaging,
SearchRequest,
ResultSetPaging
} from 'alfresco-js-api';
@Injectable()
export class ContentApiService {
constructor(
private api: AlfrescoApiService,
private preferences: UserPreferencesService
) {}
/**
* Moves a node to the trashcan.
* @param nodeId ID of the target node
* @param options Optional parameters supported by JS-API
* @returns Empty result that notifies when the deletion is complete
*/
deleteNode(
nodeId: string,
options: { permanent?: boolean } = {}
): Observable<void> {
return Observable.fromPromise(
this.api.nodesApi.deleteNode(nodeId, options)
);
}
/**
* Gets the stored information about a node.
* @param nodeId ID of the target node
* @param options Optional parameters supported by JS-API
* @returns Node information
*/
getNode(nodeId: string, options: any = {}): Observable<MinimalNodeEntity> {
const defaults = {
include: [
'path',
'properties',
'allowableOperations',
'permissions'
]
};
const queryOptions = Object.assign(defaults, options);
return Observable.fromPromise(
this.api.nodesApi.getNode(nodeId, queryOptions)
);
}
getNodeInfo(nodeId: string, options: any = {}): Observable<Node> {
const defaults = {
include: ['allowableOperations']
};
const queryOptions = Object.assign(defaults, options);
return Observable.fromPromise(
this.api.nodesApi.getNodeInfo(nodeId, queryOptions)
);
}
/**
* Gets the items contained in a folder node.
* @param nodeId ID of the target node
* @param options Optional parameters supported by JS-API
* @returns List of child items from the folder
*/
getNodeChildren(nodeId: string, options: any = {}): Observable<NodePaging> {
const defaults = {
maxItems: this.preferences.paginationSize,
skipCount: 0,
include: [
'isLocked',
'path',
'properties',
'allowableOperations',
'permissions'
]
};
const queryOptions = Object.assign(defaults, options);
return Observable.fromPromise(
this.api.nodesApi.getNodeChildren(nodeId, queryOptions)
);
}
deleteSharedLink(linkId: string): Observable<any> {
return Observable.fromPromise(
this.api.sharedLinksApi.deleteSharedLink(linkId)
);
}
getDeletedNodes(options: any = {}): Observable<DeletedNodesPaging> {
const defaults = {
include: ['path']
};
const queryOptions = Object.assign(defaults, options);
return Observable.fromPromise(
this.api.nodesApi.getDeletedNodes(queryOptions)
);
}
restoreNode(nodeId: string): Observable<MinimalNodeEntity> {
return Observable.fromPromise(this.api.nodesApi.restoreNode(nodeId));
}
purgeDeletedNode(nodeId: string): Observable<any> {
return Observable.fromPromise(
this.api.nodesApi.purgeDeletedNode(nodeId)
);
}
/**
* Gets information about a user identified by their username.
* @param personId ID of the target user
* @returns User information
*/
getPerson(
personId: string,
options?: { fields?: Array<string> }
): Observable<PersonEntry> {
return Observable.fromPromise(
this.api.peopleApi.getPerson(personId, options)
);
}
/**
* Copy a node to destination node
*
* @param nodeId The id of the node to be copied
* @param targetParentId The id of the folder-node where the node have to be copied to
* @param name The new name for the copy that would be added on the destination folder
*/
copyNode(
nodeId: string,
targetParentId: string,
name?: string,
opts?: { include?: Array<string>; fields?: Array<string> }
): Observable<NodeEntry> {
return Observable.fromPromise(
this.api.nodesApi.copyNode(nodeId, { targetParentId, name }, opts)
);
}
/**
* Gets product information for Content Services.
* @returns ProductVersionModel containing product details
*/
getRepositoryInformation(): Observable<DiscoveryEntry> {
return Observable.fromPromise(
this.api
.getInstance()
.discovery.discoveryApi.getRepositoryInformation()
);
}
getFavorites(
personId: string,
opts?: {
skipCount?: number;
maxItems?: number;
where?: string;
fields?: Array<string>;
}
): Observable<FavoritePaging> {
return Observable.fromPromise(
this.api.favoritesApi.getFavorites(personId, opts)
);
}
findSharedLinks(opts?: any): Observable<SharedLinkPaging> {
return Observable.fromPromise(
this.api.sharedLinksApi.findSharedLinks(opts)
);
}
search(request: SearchRequest): Observable<ResultSetPaging> {
return Observable.fromPromise(
this.api.searchApi.search(request)
);
}
getContentUrl(nodeId: string, attachment?: boolean): string {
return this.api.contentApi.getContentUrl(nodeId, attachment);
}
deleteSite(siteId?: string, opts?: { permanent?: boolean }): Observable<any> {
return Observable.fromPromise(
this.api.sitesApi.deleteSite(siteId, opts)
);
}
}

View File

@ -24,10 +24,11 @@
*/
import { Action } from '@ngrx/store';
import { Person } from 'alfresco-js-api';
export const SET_USER = 'SET_USER';
export class SetUserAction implements Action {
readonly type = SET_USER;
constructor(public payload: any) { }
constructor(public payload: Person) { }
}

View File

@ -24,19 +24,19 @@
*/
import { DownloadZipDialogComponent } from '@alfresco/adf-content-services';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { Injectable } from '@angular/core';
import { MatDialog } from '@angular/material';
import { Actions, Effect, ofType } from '@ngrx/effects';
import { map } from 'rxjs/operators';
import { DownloadNodesAction, DOWNLOAD_NODES } from '../actions';
import { NodeInfo } from '../models';
import { ContentApiService } from '../../services/content-api.service';
@Injectable()
export class DownloadEffects {
constructor(
private actions$: Actions,
private apiService: AlfrescoApiService,
private contentApi: ContentApiService,
private dialog: MatDialog
) {}
@ -75,7 +75,7 @@ export class DownloadEffects {
private downloadFile(node: NodeInfo) {
if (node) {
this.download(
this.apiService.contentApi.getContentUrl(node.id, true),
this.contentApi.getContentUrl(node.id, true),
node.name
);
}

View File

@ -27,7 +27,6 @@ import { Effect, Actions, ofType } from '@ngrx/effects';
import { Injectable } from '@angular/core';
import { map } from 'rxjs/operators';
import { DeleteLibraryAction, DELETE_LIBRARY } from '../actions';
import { AlfrescoApiService } from '@alfresco/adf-core';
import {
SnackbarInfoAction,
SnackbarErrorAction
@ -35,13 +34,14 @@ import {
import { Store } from '@ngrx/store';
import { AppStore } from '../states/app.state';
import { ContentManagementService } from '../../common/services/content-management.service';
import { ContentApiService } from '../../services/content-api.service';
@Injectable()
export class SiteEffects {
constructor(
private actions$: Actions,
private store: Store<AppStore>,
private apiService: AlfrescoApiService,
private contentApi: ContentApiService,
private content: ContentManagementService
) {}
@ -49,7 +49,7 @@ export class SiteEffects {
deleteLibrary$ = this.actions$.pipe(
ofType<DeleteLibraryAction>(DELETE_LIBRARY),
map(action => {
this.apiService.sitesApi.deleteSite(action.payload).then(
this.contentApi.deleteSite(action.payload).subscribe(
() => {
this.content.siteDeleted.next(action.payload);
this.store.dispatch(
@ -58,7 +58,7 @@ export class SiteEffects {
)
);
},
err => {
() => {
this.store.dispatch(
new SnackbarErrorAction(
'APP.MESSAGES.ERRORS.DELETE_LIBRARY_FAILED'

View File

@ -43,8 +43,8 @@ import {
} from '../actions';
import { ContentManagementService } from '../../common/services/content-management.service';
import { Observable } from 'rxjs/Rx';
import { AlfrescoApiService } from '@alfresco/adf-core';
import { NodeInfo, DeleteStatus, DeletedNodeInfo } from '../models';
import { ContentApiService } from '../../services/content-api.service';
@Injectable()
export class NodeEffects {
@ -52,7 +52,7 @@ export class NodeEffects {
private store: Store<AppStore>,
private actions$: Actions,
private contentManagementService: ContentManagementService,
private alfrescoApiService: AlfrescoApiService
private contentApi: ContentApiService
) {}
@Effect({ dispatch: false })
@ -113,9 +113,7 @@ export class NodeEffects {
private deleteNode(node: NodeInfo): Observable<DeletedNodeInfo> {
const { id, name } = node;
return Observable.fromPromise(
this.alfrescoApiService.nodesApi.deleteNode(id)
)
return this.contentApi.deleteNode(id)
.map(() => {
return {
id,
@ -208,9 +206,7 @@ export class NodeEffects {
private undoDeleteNode(item: DeletedNodeInfo): Observable<DeletedNodeInfo> {
const { id, name } = item;
return Observable.fromPromise(
this.alfrescoApiService.nodesApi.restoreNode(id)
)
return this.contentApi.restoreNode(id)
.map(() => {
return {
id,
@ -266,9 +262,8 @@ export class NodeEffects {
private purgeDeletedNode(node: NodeInfo): Observable<DeletedNodeInfo> {
const { id, name } = node;
const promise = this.alfrescoApiService.nodesApi.purgeDeletedNode(id);
return Observable.from(promise)
return this.contentApi.purgeDeletedNode(id)
.map(() => ({
status: 1,
id,

View File

@ -117,7 +117,9 @@ function updateUser(state: AppState, action: SetUserAction): AppState {
const lastName = user.lastName || '';
const userName = `${firstName} ${lastName}`;
const initials = [firstName[0], lastName[0]].join('');
const isAdmin = user.capabilities ? user.capabilities.isAdmin : true;
const capabilities = (<any>user).capabilities;
const isAdmin = capabilities ? capabilities.isAdmin : true;
newState.user = {
firstName,

View File

@ -42,7 +42,8 @@ import {
ContentService,
ThumbnailService,
UploadService,
PeopleContentService
PeopleContentService,
AlfrescoApiMock
} from '@alfresco/adf-core';
import { HttpClientModule } from '@angular/common/http';
import { TranslateServiceMock } from './translation.service';
@ -60,6 +61,7 @@ import { ContentManagementService } from '../common/services/content-management.
import { NodeActionsService } from '../common/services/node-actions.service';
import { NodePermissionService } from '../common/services/node-permission.service';
import { BrowsingFilesService } from '../common/services/browsing-files.service';
import { ContentApiService } from '../services/content-api.service';
@NgModule({
imports: [
@ -76,6 +78,7 @@ import { BrowsingFilesService } from '../common/services/browsing-files.service'
declarations: [TranslatePipeMock],
exports: [TranslatePipeMock, RouterTestingModule, MaterialModule],
providers: [
{ provide: AlfrescoApiService, useClass: AlfrescoApiMock },
{ provide: TranslationService, useClass: TranslationMock },
{ provide: TranslateService, useClass: TranslateServiceMock },
{ provide: TranslatePipe, useClass: TranslatePipeMock },
@ -108,7 +111,8 @@ import { BrowsingFilesService } from '../common/services/browsing-files.service'
ContentManagementService,
NodeActionsService,
NodePermissionService,
BrowsingFilesService
BrowsingFilesService,
ContentApiService
]
})
export class AppTestingModule {}