mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-31 17:38:48 +00:00
90
lib/core/services/alfresco-api.service.ts
Normal file
90
lib/core/services/alfresco-api.service.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import {
|
||||
AlfrescoApi, ContentApi, FavoritesApi, NodesApi,
|
||||
PeopleApi, RenditionsApi, SharedlinksApi, SitesApi,
|
||||
VersionsApi
|
||||
} from 'alfresco-js-api';
|
||||
import * as alfrescoApi from 'alfresco-js-api';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { StorageService } from './storage.service';
|
||||
|
||||
@Injectable()
|
||||
export class AlfrescoApiService {
|
||||
|
||||
private alfrescoApi: AlfrescoApi;
|
||||
|
||||
getInstance(): AlfrescoApi {
|
||||
return this.alfrescoApi;
|
||||
}
|
||||
|
||||
get contentApi(): ContentApi {
|
||||
return this.getInstance().content;
|
||||
}
|
||||
|
||||
get nodesApi(): NodesApi {
|
||||
return this.getInstance().nodes;
|
||||
}
|
||||
|
||||
get renditionsApi(): RenditionsApi {
|
||||
return this.getInstance().core.renditionsApi;
|
||||
}
|
||||
|
||||
get sharedLinksApi(): SharedlinksApi {
|
||||
return this.getInstance().core.sharedlinksApi;
|
||||
}
|
||||
|
||||
get sitesApi(): SitesApi {
|
||||
return this.getInstance().core.sitesApi;
|
||||
}
|
||||
|
||||
get favoritesApi(): FavoritesApi {
|
||||
return this.getInstance().core.favoritesApi;
|
||||
}
|
||||
|
||||
get peopleApi(): PeopleApi {
|
||||
return this.getInstance().core.peopleApi;
|
||||
}
|
||||
|
||||
get searchApi() {
|
||||
return this.getInstance().search.searchApi;
|
||||
}
|
||||
|
||||
get versionsApi(): VersionsApi {
|
||||
return this.getInstance().core.versionsApi;
|
||||
}
|
||||
|
||||
constructor(private appConfig: AppConfigService,
|
||||
private storage: StorageService) {
|
||||
|
||||
this.reset();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.alfrescoApi = <AlfrescoApi> new alfrescoApi({
|
||||
provider: this.storage.getItem('AUTH_TYPE'),
|
||||
ticketEcm: this.storage.getItem('ticket-ECM'),
|
||||
ticketBpm: this.storage.getItem('ticket-BPM'),
|
||||
hostEcm: this.appConfig.get<string>('ecmHost'),
|
||||
hostBpm: this.appConfig.get<string>('bpmHost'),
|
||||
contextRoot: 'alfresco',
|
||||
disableCsrf: this.storage.getItem('DISABLE_CSRF') === 'true'
|
||||
});
|
||||
}
|
||||
}
|
113
lib/core/services/apps-process.service.spec.ts
Normal file
113
lib/core/services/apps-process.service.spec.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { AppConfigServiceMock } from '../mock/app-config.service.mock';
|
||||
import { fakeApps } from '../mock/apps-service.mock';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { AppsProcessService } from './apps-process.service';
|
||||
import { LogService } from './log.service';
|
||||
import { StorageService } from './storage.service';
|
||||
|
||||
declare let jasmine: any;
|
||||
describe('Apps Service', () => {
|
||||
|
||||
let service: AppsProcessService;
|
||||
|
||||
beforeEach((() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
AppsProcessService,
|
||||
AlfrescoApiService,
|
||||
StorageService,
|
||||
LogService,
|
||||
{provide: AppConfigService, useClass: AppConfigServiceMock}
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.get(AppsProcessService);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jasmine.Ajax.install();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
it('should get the deployed apps ', (done) => {
|
||||
service.getDeployedApplications().subscribe(
|
||||
(res: any) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.length).toEqual(2);
|
||||
expect(res[0].name).toEqual('Sales-Fakes-App');
|
||||
expect(res[0].description).toEqual('desc-fake1');
|
||||
expect(res[0].deploymentId).toEqual('111');
|
||||
expect(res[1].name).toEqual('health-care-Fake');
|
||||
expect(res[1].description).toEqual('desc-fake2');
|
||||
expect(res[1].deploymentId).toEqual('444');
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(fakeApps)
|
||||
});
|
||||
});
|
||||
|
||||
it('should get the filter deployed app ', (done) => {
|
||||
service.getDeployedApplicationsByName('health-care-Fake').subscribe(
|
||||
(res: any) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.name).toEqual('health-care-Fake');
|
||||
expect(res.description).toEqual('desc-fake2');
|
||||
expect(res.deploymentId).toEqual('444');
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(fakeApps)
|
||||
});
|
||||
});
|
||||
|
||||
it('should get the deployed app details by id ', (done) => {
|
||||
service.getApplicationDetailsById(1).subscribe(
|
||||
(app: any) => {
|
||||
expect(app).toBeDefined();
|
||||
expect(app.name).toEqual('Sales-Fakes-App');
|
||||
expect(app.description).toEqual('desc-fake1');
|
||||
expect(app.deploymentId).toEqual('111');
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(fakeApps)
|
||||
});
|
||||
});
|
||||
});
|
60
lib/core/services/apps-process.service.ts
Normal file
60
lib/core/services/apps-process.service.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { AppDefinitionRepresentation } from 'alfresco-js-api';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { LogService } from './log.service';
|
||||
|
||||
@Injectable()
|
||||
export class AppsProcessService {
|
||||
|
||||
constructor(private apiService: AlfrescoApiService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
getDeployedApplications(): Observable<AppDefinitionRepresentation[]> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.appsApi.getAppDefinitions())
|
||||
.map((response: any) => {
|
||||
return response.data;
|
||||
})
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
getDeployedApplicationsByName(name: string): Observable<AppDefinitionRepresentation> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.appsApi.getAppDefinitions())
|
||||
.map((response: any) => {
|
||||
return response.data.find(app => app.name === name);
|
||||
})
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
getApplicationDetailsById(appId: number): Observable<AppDefinitionRepresentation> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.appsApi.getAppDefinitions())
|
||||
.map((response: any) => {
|
||||
return response.data.find(app => app.id === appId);
|
||||
})
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
this.logService.error(error);
|
||||
return Observable.throw(error || 'Server error');
|
||||
}
|
||||
|
||||
}
|
100
lib/core/services/auth-guard-bpm.service.spec.ts
Normal file
100
lib/core/services/auth-guard-bpm.service.spec.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, inject, TestBed } from '@angular/core/testing';
|
||||
import { Router } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { CookieServiceMock } from './../mock/cookie.service.mock';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { AppConfigModule } from '../app-config';
|
||||
import { AuthGuardBpm } from './auth-guard-bpm.service';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { CookieService } from './cookie.service';
|
||||
import { LogService } from './log.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
describe('AuthGuardService BPM', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppConfigModule,
|
||||
RouterTestingModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
AuthGuardBpm,
|
||||
SettingsService,
|
||||
AlfrescoApiService,
|
||||
AuthenticationService,
|
||||
StorageService,
|
||||
UserPreferencesService,
|
||||
{ provide: CookieService, useClass: CookieServiceMock },
|
||||
LogService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
it('if the alfresco js api is logged in should canActivate be true',
|
||||
async(inject([AuthGuardBpm, Router, SettingsService, StorageService, AuthenticationService], (auth, router, settingsService, storage, authService) => {
|
||||
spyOn(router, 'navigate');
|
||||
|
||||
authService.isBpmLoggedIn = () => {
|
||||
return true;
|
||||
};
|
||||
|
||||
expect(auth.canActivate(null, { url: '' })).toBeTruthy();
|
||||
expect(router.navigate).not.toHaveBeenCalled();
|
||||
}))
|
||||
);
|
||||
|
||||
it('if the alfresco js api is NOT logged in should canActivate be false',
|
||||
async(inject([AuthGuardBpm, Router, SettingsService, StorageService, AuthenticationService], (auth, router, settingsService, storage, authService) => {
|
||||
|
||||
spyOn(router, 'navigate');
|
||||
|
||||
authService.isBpmLoggedIn = () => {
|
||||
return false;
|
||||
};
|
||||
|
||||
expect(auth.canActivate(null, { url: '' })).toBeFalsy();
|
||||
expect(router.navigate).toHaveBeenCalled();
|
||||
}))
|
||||
);
|
||||
|
||||
it('should set redirect url',
|
||||
async(inject([AuthGuardBpm, Router, AuthenticationService], (auth, router, authService) => {
|
||||
const state = { url: 'some-url' };
|
||||
|
||||
spyOn(router, 'navigate');
|
||||
spyOn(authService, 'setRedirectUrl');
|
||||
|
||||
auth.canActivate(null , state);
|
||||
|
||||
expect(authService.setRedirectUrl).toHaveBeenCalledWith(state.url);
|
||||
}))
|
||||
);
|
||||
});
|
49
lib/core/services/auth-guard-bpm.service.ts
Normal file
49
lib/core/services/auth-guard-bpm.service.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import {
|
||||
ActivatedRouteSnapshot, CanActivate, CanActivateChild,
|
||||
Router,
|
||||
RouterStateSnapshot
|
||||
} from '@angular/router';
|
||||
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
|
||||
@Injectable()
|
||||
export class AuthGuardBpm implements CanActivate, CanActivateChild {
|
||||
constructor(private authService: AuthenticationService, private router: Router) {}
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
||||
return this.checkLogin(state.url);
|
||||
}
|
||||
|
||||
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
||||
return this.canActivate(route, state);
|
||||
}
|
||||
|
||||
checkLogin(redirectUrl: string): boolean {
|
||||
if (this.authService.isBpmLoggedIn()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.authService.setRedirectUrl(redirectUrl);
|
||||
|
||||
this.router.navigate(['/login']);
|
||||
return false;
|
||||
}
|
||||
}
|
217
lib/core/services/auth-guard-ecm.service.spec.ts
Normal file
217
lib/core/services/auth-guard-ecm.service.spec.ts
Normal file
@@ -0,0 +1,217 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, inject, TestBed } from '@angular/core/testing';
|
||||
import { Router } from '@angular/router';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { AuthGuardEcm } from './auth-guard-ecm.service';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
|
||||
class RouterProvider {
|
||||
navigate: Function = jasmine.createSpy('RouterProviderNavigate');
|
||||
}
|
||||
|
||||
class AlfrescoApiServiceProvider {
|
||||
private settings: any = {
|
||||
validateTicket: true,
|
||||
isLoggedIn: true
|
||||
};
|
||||
|
||||
constructor(settings: any = {}) {
|
||||
Object.assign(this.settings, settings);
|
||||
}
|
||||
|
||||
getInstance() {
|
||||
return {
|
||||
ecmAuth: this.ecmAuth
|
||||
};
|
||||
}
|
||||
|
||||
private get ecmAuth() {
|
||||
return {
|
||||
validateTicket: this.validateTicket.bind(this),
|
||||
isLoggedIn: this.isLoggedIn.bind(this)
|
||||
};
|
||||
}
|
||||
|
||||
private validateTicket() {
|
||||
const { validateTicket } = this.settings;
|
||||
|
||||
return validateTicket
|
||||
? Promise.resolve('Valid!')
|
||||
: Promise.reject('Invalid');
|
||||
}
|
||||
|
||||
private isLoggedIn() {
|
||||
return this.settings.isLoggedIn;
|
||||
}
|
||||
}
|
||||
|
||||
class AuthenticationServiceProvider {
|
||||
setRedirectUrl: Function = jasmine.createSpy('setRedirectUrl');
|
||||
}
|
||||
|
||||
class TestConfig {
|
||||
router: any;
|
||||
guard: any;
|
||||
auth: any;
|
||||
|
||||
private settings: any = {
|
||||
validateTicket: true,
|
||||
isLoggedIn: true
|
||||
};
|
||||
|
||||
constructor(settings: any = {}) {
|
||||
Object.assign(this.settings, settings);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
this.routerProvider,
|
||||
this.alfrescoApiServiceProvider,
|
||||
this.authenticationProvider,
|
||||
AuthGuardEcm
|
||||
]
|
||||
});
|
||||
|
||||
inject([ AuthGuardEcm, Router, AuthenticationService ], (guard: AuthGuardEcm, router: Router, auth: AuthenticationService) => {
|
||||
this.guard = guard;
|
||||
this.router = router;
|
||||
this.auth = auth;
|
||||
})();
|
||||
}
|
||||
|
||||
private get routerProvider() {
|
||||
return {
|
||||
provide: Router,
|
||||
useValue: new RouterProvider()
|
||||
};
|
||||
}
|
||||
|
||||
private get authenticationProvider() {
|
||||
return {
|
||||
provide: AuthenticationService,
|
||||
useValue: new AuthenticationServiceProvider()
|
||||
};
|
||||
}
|
||||
|
||||
private get alfrescoApiServiceProvider () {
|
||||
const { validateTicket, isLoggedIn } = this.settings;
|
||||
|
||||
return {
|
||||
provide: AlfrescoApiService,
|
||||
useValue: new AlfrescoApiServiceProvider({
|
||||
validateTicket,
|
||||
isLoggedIn
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
get navigateSpy() {
|
||||
return this.router.navigate;
|
||||
}
|
||||
}
|
||||
|
||||
describe('CanActivateLoggedIn', () => {
|
||||
describe('user is not logged in', () => {
|
||||
beforeEach(async(() => {
|
||||
this.test = new TestConfig({
|
||||
isLoggedIn: false
|
||||
});
|
||||
|
||||
const { guard, router } = this.test;
|
||||
|
||||
guard.canActivate(null, { url: '' }).then((activate) => {
|
||||
this.activate = activate;
|
||||
this.navigateSpy = router.navigate;
|
||||
});
|
||||
}));
|
||||
|
||||
it('does not allow route to activate', () => {
|
||||
expect(this.activate).toBe(false);
|
||||
});
|
||||
|
||||
it('redirects to /login', () => {
|
||||
expect(this.navigateSpy).toHaveBeenCalledWith([ '/login' ]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('user is logged in but ticket is invalid', () => {
|
||||
beforeEach(async(() => {
|
||||
this.test = new TestConfig({
|
||||
isLoggedIn: true,
|
||||
validateTicket: false
|
||||
});
|
||||
|
||||
const { guard, router } = this.test;
|
||||
|
||||
guard.canActivate(null, { url: '' }).then((activate) => {
|
||||
this.activate = activate;
|
||||
this.navigateSpy = router.navigate;
|
||||
});
|
||||
}));
|
||||
|
||||
it('does not allow route to activate', () => {
|
||||
expect(this.activate).toBe(false);
|
||||
});
|
||||
|
||||
it('redirects to /login', () => {
|
||||
expect(this.navigateSpy).toHaveBeenCalledWith([ '/login' ]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('user is logged in and ticket is valid', () => {
|
||||
beforeEach(async(() => {
|
||||
this.test = new TestConfig({
|
||||
isLoggedIn: true,
|
||||
validateTicket: true
|
||||
});
|
||||
|
||||
const { guard, router } = this.test;
|
||||
|
||||
guard.canActivate(null, { url: '' }).then((activate) => {
|
||||
this.activate = activate;
|
||||
this.navigateSpy = router.navigate;
|
||||
});
|
||||
}));
|
||||
|
||||
it('allows route to activate', () => {
|
||||
expect(this.activate).toBe(true);
|
||||
});
|
||||
|
||||
it('does not redirect', () => {
|
||||
expect(this.navigateSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('redirect url', () => {
|
||||
beforeEach(async(() => {
|
||||
this.test = new TestConfig({
|
||||
isLoggedIn: false
|
||||
});
|
||||
|
||||
const { guard, auth } = this.test;
|
||||
|
||||
guard.canActivate(null, { url: 'some-url' }).then((activate) => {
|
||||
this.auth = auth;
|
||||
});
|
||||
}));
|
||||
|
||||
it('should set redirect url', () => {
|
||||
expect(this.auth.setRedirectUrl).toHaveBeenCalledWith('some-url');
|
||||
});
|
||||
});
|
||||
});
|
57
lib/core/services/auth-guard-ecm.service.ts
Normal file
57
lib/core/services/auth-guard-ecm.service.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
|
||||
@Injectable()
|
||||
export class AuthGuardEcm implements CanActivate {
|
||||
constructor(
|
||||
private authService: AuthenticationService,
|
||||
private apiService: AlfrescoApiService,
|
||||
private router: Router) {
|
||||
}
|
||||
|
||||
private get authApi() {
|
||||
return this.apiService.getInstance().ecmAuth;
|
||||
}
|
||||
|
||||
private isLoggedIn(): Promise<boolean> {
|
||||
if (!this.authApi.isLoggedIn()) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
return this.authApi
|
||||
.validateTicket()
|
||||
.then(() => true, () => false)
|
||||
.catch(() => false);
|
||||
}
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
|
||||
|
||||
return this.isLoggedIn().then(isLoggedIn => {
|
||||
if (!isLoggedIn) {
|
||||
this.authService.setRedirectUrl(state.url);
|
||||
this.router.navigate([ '/login' ]);
|
||||
}
|
||||
|
||||
return isLoggedIn;
|
||||
});
|
||||
}
|
||||
}
|
106
lib/core/services/auth-guard.service.spec.ts
Normal file
106
lib/core/services/auth-guard.service.spec.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, inject, TestBed } from '@angular/core/testing';
|
||||
import { Router } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
import { CookieServiceMock } from './../mock/cookie.service.mock';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { AppConfigModule } from '../app-config';
|
||||
import { AuthGuard } from './auth-guard.service';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { CookieService } from './cookie.service';
|
||||
import { LogService } from './log.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
describe('AuthGuardService', () => {
|
||||
let state;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppConfigModule,
|
||||
RouterTestingModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
AuthGuard,
|
||||
SettingsService,
|
||||
AlfrescoApiService,
|
||||
AuthenticationService,
|
||||
UserPreferencesService,
|
||||
StorageService,
|
||||
{ provide: CookieService, useClass: CookieServiceMock },
|
||||
LogService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
state = { url: '' };
|
||||
});
|
||||
|
||||
it('if the alfresco js api is logged in should canActivate be true',
|
||||
async(inject([AuthGuard, Router, SettingsService, StorageService, AuthenticationService], (auth, router, settingsService, storage, authService) => {
|
||||
spyOn(router, 'navigate');
|
||||
|
||||
authService.isLoggedIn = () => {
|
||||
return true;
|
||||
};
|
||||
|
||||
expect(auth.canActivate(null, state)).toBeTruthy();
|
||||
expect(router.navigate).not.toHaveBeenCalled();
|
||||
}))
|
||||
);
|
||||
|
||||
it('if the alfresco js api is NOT logged in should canActivate be false',
|
||||
async(inject([AuthGuard, Router, SettingsService, StorageService, AuthenticationService], (auth, router, settingsService, storage, authService) => {
|
||||
|
||||
spyOn(router, 'navigate');
|
||||
|
||||
authService.isLoggedIn = () => {
|
||||
return false;
|
||||
};
|
||||
|
||||
expect(auth.canActivate(null, state)).toBeFalsy();
|
||||
expect(router.navigate).toHaveBeenCalled();
|
||||
}))
|
||||
);
|
||||
|
||||
it('should set redirect url',
|
||||
async(inject([AuthGuard, Router, AuthenticationService], (auth, router, authService) => {
|
||||
state.url = 'some-url';
|
||||
|
||||
spyOn(router, 'navigate');
|
||||
spyOn(authService, 'setRedirectUrl');
|
||||
|
||||
auth.canActivate(null , state);
|
||||
|
||||
expect(authService.setRedirectUrl).toHaveBeenCalledWith(state.url);
|
||||
}))
|
||||
);
|
||||
});
|
51
lib/core/services/auth-guard.service.ts
Normal file
51
lib/core/services/auth-guard.service.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import {
|
||||
ActivatedRouteSnapshot, CanActivate, CanActivateChild,
|
||||
Router,
|
||||
RouterStateSnapshot
|
||||
} from '@angular/router';
|
||||
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
|
||||
@Injectable()
|
||||
export class AuthGuard implements CanActivate, CanActivateChild {
|
||||
constructor(private authService: AuthenticationService, private router: Router) {}
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
||||
const redirectUrl = state.url;
|
||||
|
||||
return this.checkLogin(redirectUrl);
|
||||
}
|
||||
|
||||
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
|
||||
return this.canActivate(route, state);
|
||||
}
|
||||
|
||||
checkLogin(redirectUrl: string): boolean {
|
||||
if (this.authService.isLoggedIn()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.authService.setRedirectUrl(redirectUrl);
|
||||
|
||||
this.router.navigate(['/login']);
|
||||
return false;
|
||||
}
|
||||
}
|
473
lib/core/services/authentication.service.spec.ts
Normal file
473
lib/core/services/authentication.service.spec.ts
Normal file
@@ -0,0 +1,473 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, TestBed } from '@angular/core/testing';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { CookieServiceMock } from './../mock/cookie.service.mock';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { AppConfigModule } from '../app-config';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { CookieService } from './cookie.service';
|
||||
import { LogService } from './log.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
describe('AuthenticationService', () => {
|
||||
let apiService: AlfrescoApiService;
|
||||
let authService: AuthenticationService;
|
||||
let settingsService: SettingsService;
|
||||
let preferences: UserPreferencesService;
|
||||
let storage: StorageService;
|
||||
let cookie: CookieService;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppConfigModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
SettingsService,
|
||||
AlfrescoApiService,
|
||||
AuthenticationService,
|
||||
StorageService,
|
||||
UserPreferencesService,
|
||||
{ provide: CookieService, useClass: CookieServiceMock },
|
||||
LogService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
apiService = TestBed.get(AlfrescoApiService);
|
||||
authService = TestBed.get(AuthenticationService);
|
||||
settingsService = TestBed.get(SettingsService);
|
||||
preferences = TestBed.get(UserPreferencesService);
|
||||
cookie = TestBed.get(CookieService);
|
||||
storage = TestBed.get(StorageService);
|
||||
storage.clear();
|
||||
|
||||
jasmine.Ajax.install();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
describe('remembe me', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
preferences.authType = 'ECM';
|
||||
});
|
||||
|
||||
it('[ECM] should save the remember me cookie as a session cookie after successful login', (done) => {
|
||||
authService.login('fake-username', 'fake-password', false).subscribe(() => {
|
||||
expect(cookie['ALFRESCO_REMEMBER_ME']).not.toBeUndefined();
|
||||
expect(cookie['ALFRESCO_REMEMBER_ME'].expiration).toBeNull();
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 201,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
|
||||
});
|
||||
});
|
||||
|
||||
it('[ECM] should save the remember me cookie as a persistent cookie after successful login', (done) => {
|
||||
authService.login('fake-username', 'fake-password', true).subscribe(() => {
|
||||
expect(cookie['ALFRESCO_REMEMBER_ME']).not.toBeUndefined();
|
||||
expect(cookie['ALFRESCO_REMEMBER_ME'].expiration).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 201,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
|
||||
});
|
||||
});
|
||||
|
||||
it('[ECM] should not save the remember me cookie after failed login', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(
|
||||
(res) => {},
|
||||
(err: any) => {
|
||||
expect(cookie['ALFRESCO_REMEMBER_ME']).toBeUndefined();
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 403,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({
|
||||
'error': {
|
||||
'errorKey': 'Login failed',
|
||||
'statusCode': 403,
|
||||
'briefSummary': '05150009 Login failed',
|
||||
'stackTrace': 'For security reasons the stack trace is no longer displayed, but the property is kept for previous versions.',
|
||||
'descriptionURL': 'https://api-explorer.alfresco.com'
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the setting is ECM', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
preferences.authType = 'ECM';
|
||||
});
|
||||
|
||||
it('[ECM] should return an ECM ticket after the login done', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(() => {
|
||||
expect(authService.isLoggedIn()).toBe(true);
|
||||
expect(authService.getTicketEcm()).toEqual('fake-post-ticket');
|
||||
expect(authService.isEcmLoggedIn()).toBe(true);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 201,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
|
||||
});
|
||||
});
|
||||
|
||||
it('[ECM] should save only ECM ticket on localStorage', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(() => {
|
||||
expect(authService.isLoggedIn()).toBe(true);
|
||||
expect(authService.getTicketBpm()).toBeNull();
|
||||
expect(apiService.getInstance().bpmAuth.isLoggedIn()).toBeFalsy();
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 201,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
|
||||
});
|
||||
});
|
||||
|
||||
xit('[ECM] should return ticket undefined when the credentials are wrong', (done) => {
|
||||
authService.login('fake-wrong-username', 'fake-wrong-password').subscribe(
|
||||
(res) => {
|
||||
},
|
||||
(err: any) => {
|
||||
expect(authService.isLoggedIn()).toBe(false);
|
||||
expect(authService.getTicketEcm()).toBe(null);
|
||||
expect(authService.isEcmLoggedIn()).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 403,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({
|
||||
'error': {
|
||||
'errorKey': 'Login failed',
|
||||
'statusCode': 403,
|
||||
'briefSummary': '05150009 Login failed',
|
||||
'stackTrace': 'For security reasons the stack trace is no longer displayed, but the property is kept for previous versions.',
|
||||
'descriptionURL': 'https://api-explorer.alfresco.com'
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it('[ECM] should login in the ECM if no provider are defined calling the login', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(() => {
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 201,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
|
||||
});
|
||||
});
|
||||
|
||||
it('[ECM] should return a ticket undefined after logout', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(() => {
|
||||
authService.logout().subscribe(() => {
|
||||
expect(authService.isLoggedIn()).toBe(false);
|
||||
expect(authService.getTicketEcm()).toBe(null);
|
||||
expect(authService.isEcmLoggedIn()).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 204
|
||||
});
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 201,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
|
||||
});
|
||||
});
|
||||
|
||||
it('[ECM] ticket should be deleted only after logout request is accepted', (done) => {
|
||||
|
||||
authService.login('fake-username', 'fake-password').subscribe(() => {
|
||||
let logoutPromise = authService.logout();
|
||||
|
||||
expect(authService.getTicketEcm()).toBe('fake-post-ticket');
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 204
|
||||
});
|
||||
|
||||
logoutPromise.subscribe(() => {
|
||||
expect(authService.isLoggedIn()).toBe(false);
|
||||
expect(authService.isEcmLoggedIn()).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 201,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
|
||||
});
|
||||
});
|
||||
|
||||
it('[ECM] should return false if the user is not logged in', () => {
|
||||
expect(authService.isLoggedIn()).toBe(false);
|
||||
expect(authService.isEcmLoggedIn()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the setting is BPM', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
preferences.authType = 'BPM';
|
||||
});
|
||||
|
||||
it('[BPM] should return an BPM ticket after the login done', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(() => {
|
||||
expect(authService.isLoggedIn()).toBe(true);
|
||||
expect(authService.getTicketBpm()).toEqual('Basic ZmFrZS11c2VybmFtZTpmYWtlLXBhc3N3b3Jk');
|
||||
expect(authService.isBpmLoggedIn()).toBe(true);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200
|
||||
});
|
||||
});
|
||||
|
||||
it('[BPM] should save only BPM ticket on localStorage', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(() => {
|
||||
expect(authService.isLoggedIn()).toBe(true);
|
||||
expect(authService.getTicketEcm()).toBeNull();
|
||||
expect(apiService.getInstance().ecmAuth.isLoggedIn()).toBeFalsy();
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 201,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
|
||||
});
|
||||
});
|
||||
|
||||
xit('[BPM] should return ticket undefined when the credentials are wrong', (done) => {
|
||||
authService.login('fake-wrong-username', 'fake-wrong-password').subscribe(
|
||||
(res) => {
|
||||
},
|
||||
(err: any) => {
|
||||
expect(authService.isLoggedIn()).toBe(false, 'isLoggedIn');
|
||||
expect(authService.getTicketBpm()).toBe(null, 'getTicketBpm');
|
||||
expect(authService.isBpmLoggedIn()).toBe(false, 'isBpmLoggedIn');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 403
|
||||
});
|
||||
});
|
||||
|
||||
it('[BPM] ticket should be deleted only after logout request is accepted', (done) => {
|
||||
|
||||
authService.login('fake-username', 'fake-password').subscribe(() => {
|
||||
let logoutPromise = authService.logout();
|
||||
|
||||
expect(authService.getTicketBpm()).toBe('Basic ZmFrZS11c2VybmFtZTpmYWtlLXBhc3N3b3Jk');
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200
|
||||
});
|
||||
|
||||
logoutPromise.subscribe(() => {
|
||||
expect(authService.isLoggedIn()).toBe(false);
|
||||
expect(authService.isBpmLoggedIn()).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200
|
||||
});
|
||||
});
|
||||
|
||||
it('[BPM] should return a ticket undefined after logout', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(() => {
|
||||
authService.logout().subscribe(() => {
|
||||
expect(authService.isLoggedIn()).toBe(false);
|
||||
expect(authService.getTicketBpm()).toBe(null);
|
||||
expect(authService.isBpmLoggedIn()).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200
|
||||
});
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200
|
||||
});
|
||||
});
|
||||
|
||||
it('[BPM] should return an error when the logout return error', (done) => {
|
||||
authService.logout().subscribe(
|
||||
(res) => {
|
||||
},
|
||||
(err: any) => {
|
||||
expect(err).toBeDefined();
|
||||
expect(authService.getTicketBpm()).toBe(null);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 403
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the setting is both ECM and BPM ', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
preferences.authType = 'ALL';
|
||||
});
|
||||
|
||||
it('[ALL] should return both ECM and BPM tickets after the login done', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(() => {
|
||||
expect(authService.isLoggedIn()).toBe(true);
|
||||
expect(authService.getTicketEcm()).toEqual('fake-post-ticket');
|
||||
expect(authService.getTicketBpm()).toEqual('Basic ZmFrZS11c2VybmFtZTpmYWtlLXBhc3N3b3Jk');
|
||||
expect(authService.isBpmLoggedIn()).toBe(true);
|
||||
expect(authService.isEcmLoggedIn()).toBe(true);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.at(0).respondWith({
|
||||
'status': 201,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.at(1).respondWith({
|
||||
'status': 200
|
||||
});
|
||||
});
|
||||
|
||||
xit('[ALL] should return login fail if only ECM call fail', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(
|
||||
(res) => {
|
||||
},
|
||||
(err: any) => {
|
||||
expect(authService.isLoggedIn()).toBe(false, 'isLoggedIn');
|
||||
expect(authService.getTicketEcm()).toBe(null, 'getTicketEcm');
|
||||
expect(authService.getTicketBpm()).toBe(null, 'getTicketBpm');
|
||||
expect(authService.isEcmLoggedIn()).toBe(false, 'isEcmLoggedIn');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.at(0).respondWith({
|
||||
'status': 403
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.at(1).respondWith({
|
||||
'status': 200
|
||||
});
|
||||
});
|
||||
|
||||
xit('[ALL] should return login fail if only BPM call fail', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(
|
||||
(res) => {
|
||||
},
|
||||
(err: any) => {
|
||||
expect(authService.isLoggedIn()).toBe(false);
|
||||
expect(authService.getTicketEcm()).toBe(null);
|
||||
expect(authService.getTicketBpm()).toBe(null);
|
||||
expect(authService.isBpmLoggedIn()).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.at(0).respondWith({
|
||||
'status': 201,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.at(1).respondWith({
|
||||
'status': 403
|
||||
});
|
||||
});
|
||||
|
||||
xit('[ALL] should return ticket undefined when the credentials are wrong', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(
|
||||
(res) => {
|
||||
},
|
||||
(err: any) => {
|
||||
expect(authService.isLoggedIn()).toBe(false);
|
||||
expect(authService.getTicketEcm()).toBe(null);
|
||||
expect(authService.getTicketBpm()).toBe(null);
|
||||
expect(authService.isBpmLoggedIn()).toBe(false);
|
||||
expect(authService.isEcmLoggedIn()).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.at(0).respondWith({
|
||||
'status': 403
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.at(1).respondWith({
|
||||
'status': 403
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should set/get redirectUrl', () => {
|
||||
authService.setRedirectUrl('some-url');
|
||||
|
||||
expect(authService.getRedirectUrl()).toBe('some-url');
|
||||
});
|
||||
});
|
249
lib/core/services/authentication.service.ts
Normal file
249
lib/core/services/authentication.service.ts
Normal file
@@ -0,0 +1,249 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { Observable, Subject } from 'rxjs/Rx';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { CookieService } from './cookie.service';
|
||||
import { LogService } from './log.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
const REMEMBER_ME_COOKIE_KEY = 'ALFRESCO_REMEMBER_ME';
|
||||
const REMEMBER_ME_UNTIL = 1000 * 60 * 60 * 24 * 30 ;
|
||||
|
||||
@Injectable()
|
||||
export class AuthenticationService {
|
||||
private redirectUrl: string = '';
|
||||
|
||||
onLogin: Subject<any> = new Subject<any>();
|
||||
onLogout: Subject<any> = new Subject<any>();
|
||||
|
||||
constructor(
|
||||
private preferences: UserPreferencesService,
|
||||
private alfrescoApi: AlfrescoApiService,
|
||||
private storage: StorageService,
|
||||
private cookie: CookieService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* The method return true if the user is logged in
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isLoggedIn(): boolean {
|
||||
return !!this.alfrescoApi.getInstance().isLoggedIn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Method to delegate to POST login
|
||||
* @param username
|
||||
* @param password
|
||||
* @returns {Observable<R>|Observable<T>}
|
||||
*/
|
||||
login(username: string, password: string, rememberMe: boolean = false): Observable<{ type: string, ticket: any }> {
|
||||
this.removeTicket();
|
||||
return Observable.fromPromise(this.callApiLogin(username, password))
|
||||
.map((response: any) => {
|
||||
this.saveRememberMeCookie(rememberMe);
|
||||
this.saveTickets();
|
||||
this.onLogin.next(response);
|
||||
return {
|
||||
type: this.preferences.authType,
|
||||
ticket: response
|
||||
};
|
||||
})
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
/**
|
||||
* The method save the "remember me" cookie as a long life cookie or a session cookie
|
||||
* depending on the given paramter
|
||||
*/
|
||||
private saveRememberMeCookie(rememberMe: boolean): void {
|
||||
let expiration = null;
|
||||
|
||||
if (rememberMe) {
|
||||
expiration = new Date();
|
||||
const time = expiration.getTime();
|
||||
const expireTime = time + REMEMBER_ME_UNTIL;
|
||||
expiration.setTime(expireTime);
|
||||
}
|
||||
this.cookie.setItem(REMEMBER_ME_COOKIE_KEY, '1', expiration, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* The method retrieve whether the "remember me" cookie was set or not
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
private isRememberMeSet(): boolean {
|
||||
return (this.cookie.getItem(REMEMBER_ME_COOKIE_KEY) === null) ? false : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the alfresco Api with user and password end call the login method
|
||||
* @param username
|
||||
* @param password
|
||||
* @returns {*|Observable<any>}
|
||||
*/
|
||||
private callApiLogin(username: string, password: string) {
|
||||
return this.alfrescoApi.getInstance().login(username, password);
|
||||
}
|
||||
|
||||
/**
|
||||
* The method remove the ticket from the Storage
|
||||
*
|
||||
* @returns {Observable<R>|Observable<T>}
|
||||
*/
|
||||
logout() {
|
||||
return Observable.fromPromise(this.callApiLogout())
|
||||
.do(response => {
|
||||
this.removeTicket();
|
||||
this.onLogout.next(response);
|
||||
return response;
|
||||
})
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {*|Observable<string>|Observable<any>|Promise<T>}
|
||||
*/
|
||||
private callApiLogout(): Promise<any> {
|
||||
if (this.alfrescoApi.getInstance()) {
|
||||
return this.alfrescoApi.getInstance().logout();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the login ticket from Storage
|
||||
*/
|
||||
removeTicket(): void {
|
||||
this.storage.removeItem('ticket-ECM');
|
||||
this.storage.removeItem('ticket-BPM');
|
||||
this.alfrescoApi.getInstance().setTicket(undefined, undefined);
|
||||
}
|
||||
|
||||
/**
|
||||
* The method return the ECM ticket stored in the Storage
|
||||
* @returns ticket
|
||||
*/
|
||||
getTicketEcm(): string | null {
|
||||
return this.storage.getItem('ticket-ECM');
|
||||
}
|
||||
|
||||
/**
|
||||
* The method return the BPM ticket stored in the Storage
|
||||
* @returns ticket
|
||||
*/
|
||||
getTicketBpm(): string | null {
|
||||
return this.storage.getItem('ticket-BPM');
|
||||
}
|
||||
|
||||
getTicketEcmBase64(): string | null {
|
||||
let ticket = this.storage.getItem('ticket-ECM');
|
||||
if (ticket) {
|
||||
return 'Basic ' + btoa(ticket);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The method save the ECM and BPM ticket in the Storage
|
||||
*/
|
||||
saveTickets(): void {
|
||||
this.saveTicketEcm();
|
||||
this.saveTicketBpm();
|
||||
}
|
||||
|
||||
/**
|
||||
* The method save the ECM ticket in the Storage
|
||||
*/
|
||||
saveTicketEcm(): void {
|
||||
if (this.alfrescoApi.getInstance() && this.alfrescoApi.getInstance().getTicketEcm()) {
|
||||
this.storage.setItem('ticket-ECM', this.alfrescoApi.getInstance().getTicketEcm());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The method save the BPM ticket in the Storage
|
||||
*/
|
||||
saveTicketBpm(): void {
|
||||
if (this.alfrescoApi.getInstance() && this.alfrescoApi.getInstance().getTicketBpm()) {
|
||||
this.storage.setItem('ticket-BPM', this.alfrescoApi.getInstance().getTicketBpm());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The method return true if user is logged in on ecm provider
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isEcmLoggedIn(): boolean {
|
||||
return this.isRememberMeSet() && this.alfrescoApi.getInstance().ecmAuth && !!this.alfrescoApi.getInstance().ecmAuth.isLoggedIn();
|
||||
}
|
||||
|
||||
/**
|
||||
* The method return true if user is logged in on bpm provider
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isBpmLoggedIn(): boolean {
|
||||
return this.isRememberMeSet() && this.alfrescoApi.getInstance().bpmAuth && !!this.alfrescoApi.getInstance().bpmAuth.isLoggedIn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ECM username
|
||||
*
|
||||
* @returns {string} The username value
|
||||
*
|
||||
* @memberof AuthenticationService
|
||||
*/
|
||||
getEcmUsername(): string {
|
||||
return this.alfrescoApi.getInstance().ecmAuth.username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the BPM username
|
||||
*
|
||||
* @returns {string} The username value
|
||||
*
|
||||
* @memberof AuthenticationService
|
||||
*/
|
||||
getBpmUsername(): string {
|
||||
return this.alfrescoApi.getInstance().bpmAuth.username;
|
||||
}
|
||||
|
||||
setRedirectUrl(url: string) {
|
||||
this.redirectUrl = url;
|
||||
}
|
||||
|
||||
getRedirectUrl(): string {
|
||||
return this.redirectUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* The method write the error in the console browser
|
||||
* @param error
|
||||
* @returns {ErrorObservable}
|
||||
*/
|
||||
handleError(error: any): Observable<any> {
|
||||
this.logService.error('Error when logging in', error);
|
||||
return Observable.throw(error || 'Server error');
|
||||
}
|
||||
}
|
34
lib/core/services/card-item-types.service.ts
Normal file
34
lib/core/services/card-item-types.service.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable, Type } from '@angular/core';
|
||||
import { CardViewDateItemComponent } from '../card-view/card-view-dateitem.component';
|
||||
import { CardViewMapItemComponent } from '../card-view/card-view-mapitem.component';
|
||||
import { CardViewTextItemComponent } from '../card-view/card-view-textitem.component';
|
||||
import { DynamicComponentMapper, DynamicComponentResolveFunction, DynamicComponentResolver } from '../services/dynamic-component-mapper.service';
|
||||
|
||||
@Injectable()
|
||||
export class CardItemTypeService extends DynamicComponentMapper {
|
||||
|
||||
protected defaultValue: Type<{}> = CardViewTextItemComponent;
|
||||
|
||||
protected types: { [key: string]: DynamicComponentResolveFunction } = {
|
||||
'text': DynamicComponentResolver.fromType(CardViewTextItemComponent),
|
||||
'date': DynamicComponentResolver.fromType(CardViewDateItemComponent),
|
||||
'map': DynamicComponentResolver.fromType(CardViewMapItemComponent)
|
||||
};
|
||||
}
|
54
lib/core/services/card-view-update.service.ts
Normal file
54
lib/core/services/card-view-update.service.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
import { CardViewBaseItemModel } from '../models/card-view-baseitem.model';
|
||||
|
||||
export interface UpdateNotification {
|
||||
target: any;
|
||||
changed: any;
|
||||
}
|
||||
|
||||
export interface ClickNotification {
|
||||
target: any;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class CardViewUpdateService {
|
||||
|
||||
// Observable sources
|
||||
private itemUpdatedSource = new Subject<UpdateNotification>();
|
||||
|
||||
// Observable streams
|
||||
public itemUpdated$ = this.itemUpdatedSource.asObservable();
|
||||
|
||||
public itemClicked$: Subject<ClickNotification> = new Subject<ClickNotification>();
|
||||
|
||||
update(property: CardViewBaseItemModel, changed: any) {
|
||||
this.itemUpdatedSource.next({
|
||||
target: property,
|
||||
changed
|
||||
});
|
||||
}
|
||||
|
||||
clicked(property: CardViewBaseItemModel) {
|
||||
this.itemClicked$.next({
|
||||
target: property
|
||||
});
|
||||
}
|
||||
}
|
194
lib/core/services/comment-process.service.spec.ts
Normal file
194
lib/core/services/comment-process.service.spec.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, TestBed } from '@angular/core/testing';
|
||||
import { CommentProcessModel } from '../models';
|
||||
import { AppConfigServiceMock } from '../mock/app-config.service.mock';
|
||||
import { fakeProcessComment, fakeTasksComment, fakeUser1 } from '../mock/comment-process-service.mock';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { CommentProcessService } from './comment-process.service';
|
||||
import { LogService } from './log.service';
|
||||
import { StorageService } from './storage.service';
|
||||
|
||||
declare let jasmine: any;
|
||||
describe('Comment ProcessService Service', () => {
|
||||
|
||||
let service: CommentProcessService;
|
||||
let alfrescoApi: any;
|
||||
|
||||
beforeEach((() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
CommentProcessService,
|
||||
AlfrescoApiService,
|
||||
StorageService,
|
||||
LogService,
|
||||
{provide: AppConfigService, useClass: AppConfigServiceMock}
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.get(CommentProcessService);
|
||||
alfrescoApi = TestBed.get(AlfrescoApiService).getInstance();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
jasmine.Ajax.install();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
describe('Process comments', () => {
|
||||
|
||||
const processId = '1001';
|
||||
|
||||
describe('get comments', () => {
|
||||
|
||||
let getProcessInstanceComments: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
getProcessInstanceComments = spyOn(alfrescoApi.activiti.commentsApi, 'getProcessInstanceComments')
|
||||
.and
|
||||
.returnValue(Promise.resolve({data: [fakeProcessComment, fakeProcessComment]}));
|
||||
});
|
||||
|
||||
it('should return the correct number of comments', async(() => {
|
||||
service.getProcessInstanceComments(processId).subscribe((tasks) => {
|
||||
expect(tasks.length).toBe(2);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should return the correct comment data', async(() => {
|
||||
service.getProcessInstanceComments(processId).subscribe((comments) => {
|
||||
let comment: any = comments[0];
|
||||
expect(comment.id).toBe(fakeProcessComment.id);
|
||||
expect(comment.created).toBe(fakeProcessComment.created);
|
||||
expect(comment.message).toBe(fakeProcessComment.message);
|
||||
expect(comment.createdBy.id).toBe(fakeProcessComment.createdBy.id);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should call service to fetch process instance comments', () => {
|
||||
service.getProcessInstanceComments(processId);
|
||||
expect(getProcessInstanceComments).toHaveBeenCalledWith(processId);
|
||||
});
|
||||
|
||||
it('should return a default error if no data is returned by the API', async(() => {
|
||||
getProcessInstanceComments = getProcessInstanceComments.and.returnValue(Promise.reject(null));
|
||||
service.getProcessInstanceComments(processId).subscribe(
|
||||
() => {
|
||||
},
|
||||
(res) => {
|
||||
expect(res).toBe('Server error');
|
||||
}
|
||||
);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
describe('add comment', () => {
|
||||
|
||||
const message = 'Test message';
|
||||
let addProcessInstanceComment: jasmine.Spy;
|
||||
|
||||
beforeEach(() => {
|
||||
addProcessInstanceComment = spyOn(alfrescoApi.activiti.commentsApi, 'addProcessInstanceComment')
|
||||
.and
|
||||
.returnValue(Promise.resolve(fakeProcessComment));
|
||||
});
|
||||
|
||||
it('should call service to add comment', () => {
|
||||
service.addProcessInstanceComment(processId, message);
|
||||
expect(addProcessInstanceComment).toHaveBeenCalledWith({
|
||||
message: message
|
||||
}, processId);
|
||||
});
|
||||
|
||||
it('should return the created comment', async(() => {
|
||||
service.addProcessInstanceComment(processId, message).subscribe((comment) => {
|
||||
expect(comment.id).toBe(fakeProcessComment.id);
|
||||
expect(comment.created).toBe(fakeProcessComment.created);
|
||||
expect(comment.message).toBe(fakeProcessComment.message);
|
||||
expect(comment.createdBy).toBe(fakeProcessComment.createdBy);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should return a default error if no data is returned by the API', async(() => {
|
||||
addProcessInstanceComment = addProcessInstanceComment.and.returnValue(Promise.reject(null));
|
||||
service.addProcessInstanceComment(processId, message).subscribe(
|
||||
() => {
|
||||
},
|
||||
(res) => {
|
||||
expect(res).toBe('Server error');
|
||||
}
|
||||
);
|
||||
}));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('Task comments', () => {
|
||||
|
||||
it('should add a comment task ', (done) => {
|
||||
service.addTaskComment('999', 'fake-comment-message').subscribe(
|
||||
(res: CommentProcessModel) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.id).not.toEqual(null);
|
||||
expect(res.message).toEqual('fake-comment-message');
|
||||
expect(res.created).not.toEqual(null);
|
||||
expect(res.createdBy.email).toEqual('fake-email@dom.com');
|
||||
expect(res.createdBy.firstName).toEqual('firstName');
|
||||
expect(res.createdBy.lastName).toEqual('lastName');
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({
|
||||
id: '111', message: 'fake-comment-message',
|
||||
createdBy: fakeUser1,
|
||||
created: '2016-07-15T11:19:17.440+0000'
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
it('should return the tasks comments ', (done) => {
|
||||
service.getTaskComments('999').subscribe(
|
||||
(res: CommentProcessModel[]) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res.length).toEqual(2);
|
||||
expect(res[0].message).toEqual('fake-message-1');
|
||||
expect(res[1].message).toEqual('fake-message-2');
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(fakeTasksComment)
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
82
lib/core/services/comment-process.service.ts
Normal file
82
lib/core/services/comment-process.service.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { CommentProcessModel } from '../models/comment-process.model';
|
||||
import { UserProcessModel } from '../models/user-process.model';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { LogService } from './log.service';
|
||||
|
||||
@Injectable()
|
||||
export class CommentProcessService {
|
||||
|
||||
constructor(private apiService: AlfrescoApiService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
addTaskComment(taskId: string, message: string): Observable<CommentProcessModel> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.taskApi.addTaskComment({message: message}, taskId))
|
||||
.map(res => res)
|
||||
.map((response: CommentProcessModel) => {
|
||||
return new CommentProcessModel({id: response.id, message: response.message, created: response.created, createdBy: response.createdBy});
|
||||
}).catch(err => this.handleError(err));
|
||||
|
||||
}
|
||||
|
||||
getTaskComments(taskId: string): Observable<CommentProcessModel[]> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.taskApi.getTaskComments(taskId))
|
||||
.map(res => res)
|
||||
.map((response: any) => {
|
||||
let comments: CommentProcessModel[] = [];
|
||||
response.data.forEach((comment: CommentProcessModel) => {
|
||||
let user = new UserProcessModel(comment.createdBy);
|
||||
comments.push(new CommentProcessModel({id: comment.id, message: comment.message, created: comment.created, createdBy: user}));
|
||||
});
|
||||
return comments;
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
getProcessInstanceComments(processInstanceId: string): Observable<CommentProcessModel[]> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().activiti.commentsApi.getProcessInstanceComments(processInstanceId))
|
||||
.map(res => res)
|
||||
.map((response: any) => {
|
||||
let comments: CommentProcessModel[] = [];
|
||||
response.data.forEach((comment: CommentProcessModel) => {
|
||||
let user = new UserProcessModel(comment.createdBy);
|
||||
comments.push(new CommentProcessModel({id: comment.id, message: comment.message, created: comment.created, createdBy: user}));
|
||||
});
|
||||
return comments;
|
||||
}).catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
addProcessInstanceComment(processInstanceId: string, message: string): Observable<CommentProcessModel> {
|
||||
return Observable.fromPromise(
|
||||
this.apiService.getInstance().activiti.commentsApi.addProcessInstanceComment({ message: message }, processInstanceId)
|
||||
)
|
||||
.map((response: CommentProcessModel) => {
|
||||
return new CommentProcessModel({id: response.id, message: response.message, created: response.created, createdBy: response.createdBy});
|
||||
}).catch(err => this.handleError(err));
|
||||
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
this.logService.error(error);
|
||||
return Observable.throw(error || 'Server error');
|
||||
}
|
||||
|
||||
}
|
168
lib/core/services/content.service.spec.ts
Normal file
168
lib/core/services/content.service.spec.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, TestBed } from '@angular/core/testing';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { CookieServiceMock } from '../mock/cookie.service.mock';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { ContentService } from './content.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { AppConfigModule } from '../app-config/app-config.module';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { CookieService } from './cookie.service';
|
||||
import { LogService } from './log.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
describe('ContentService', () => {
|
||||
|
||||
let contentService: ContentService;
|
||||
let authService: AuthenticationService;
|
||||
let settingsService: SettingsService;
|
||||
let storage: StorageService;
|
||||
let node: any;
|
||||
|
||||
const nodeId = 'fake-node-id';
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppConfigModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
})
|
||||
],
|
||||
declarations: [],
|
||||
providers: [
|
||||
AlfrescoApiService,
|
||||
ContentService,
|
||||
AuthenticationService,
|
||||
SettingsService,
|
||||
StorageService,
|
||||
UserPreferencesService,
|
||||
{provide: CookieService, useClass: CookieServiceMock},
|
||||
LogService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
authService = TestBed.get(AuthenticationService);
|
||||
settingsService = TestBed.get(SettingsService);
|
||||
contentService = TestBed.get(ContentService);
|
||||
storage = TestBed.get(StorageService);
|
||||
storage.clear();
|
||||
|
||||
node = {
|
||||
entry: {
|
||||
id: nodeId
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.Ajax.install();
|
||||
|
||||
let appConfig: AppConfigService = TestBed.get(AppConfigService);
|
||||
appConfig.config = {
|
||||
ecmHost: 'http://localhost:9876/ecm'
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
settingsService.setProviders('ECM');
|
||||
});
|
||||
|
||||
it('should return a valid content URL', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(() => {
|
||||
expect(contentService.getContentUrl(node)).toBe('http://localhost:9876/ecm/alfresco/api/' +
|
||||
'-default-/public/alfresco/versions/1/nodes/fake-node-id/content?attachment=false&alf_ticket=fake-post-ticket');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 201,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
|
||||
});
|
||||
});
|
||||
|
||||
it('should return a valid thumbnail URL', (done) => {
|
||||
authService.login('fake-username', 'fake-password').subscribe(() => {
|
||||
expect(contentService.getDocumentThumbnailUrl(node))
|
||||
.toBe('http://localhost:9876/ecm/alfresco/api/-default-/public/alfresco' +
|
||||
'/versions/1/nodes/fake-node-id/renditions/doclib/content?attachment=false&alf_ticket=fake-post-ticket');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 201,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'entry': {'id': 'fake-post-ticket', 'userId': 'admin'}})
|
||||
});
|
||||
});
|
||||
|
||||
it('should havePermission be false if allowableOperation is not present in the node', () => {
|
||||
let permissionNode = {};
|
||||
expect(contentService.hasPermission(permissionNode, 'create')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should havePermission be true if allowableOperation is present and you have the permission for the request operation', () => {
|
||||
let permissionNode = {allowableOperations: ['delete', 'update', 'create', 'updatePermissions']};
|
||||
|
||||
expect(contentService.hasPermission(permissionNode, 'create')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should havePermission be false if allowableOperation is present but you don\'t have the permission for the request operation', () => {
|
||||
let permissionNode = {allowableOperations: ['delete', 'update', 'updatePermissions']};
|
||||
expect(contentService.hasPermission(permissionNode, 'create')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should havePermission works in the opposite way with negate value', () => {
|
||||
let permissionNode = {allowableOperations: ['delete', 'update', 'updatePermissions']};
|
||||
expect(contentService.hasPermission(permissionNode, '!create')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should havePermission return false id no permission parameter are passed', () => {
|
||||
let permissionNode = {allowableOperations: ['delete', 'update', 'updatePermissions']};
|
||||
expect(contentService.hasPermission(permissionNode, null)).toBeFalsy();
|
||||
});
|
||||
|
||||
describe('Download blob', () => {
|
||||
|
||||
it('Should use native msSaveOrOpenBlob if the browser is IE', (done) => {
|
||||
|
||||
let navigatorAny: any = window.navigator;
|
||||
|
||||
navigatorAny.__defineGetter__('msSaveOrOpenBlob', () => {
|
||||
done();
|
||||
});
|
||||
|
||||
let blob = new Blob([''], {type: 'text/html'});
|
||||
contentService.downloadBlob(blob, 'test_ie');
|
||||
});
|
||||
});
|
||||
});
|
231
lib/core/services/content.service.ts
Normal file
231
lib/core/services/content.service.ts
Normal file
@@ -0,0 +1,231 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { ContentApi, MinimalNodeEntryEntity } from 'alfresco-js-api';
|
||||
import { Observable, Subject } from 'rxjs/Rx';
|
||||
import { FolderCreatedEvent } from '../events/folder-created.event';
|
||||
import { PermissionsEnum } from '../models/permissions.enum';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { LogService } from './log.service';
|
||||
|
||||
@Injectable()
|
||||
export class ContentService {
|
||||
|
||||
private saveData: Function;
|
||||
|
||||
folderCreated: Subject<FolderCreatedEvent> = new Subject<FolderCreatedEvent>();
|
||||
folderCreate: Subject<MinimalNodeEntryEntity> = new Subject<MinimalNodeEntryEntity>();
|
||||
folderEdit: Subject<MinimalNodeEntryEntity> = new Subject<MinimalNodeEntryEntity>();
|
||||
|
||||
constructor(public authService: AuthenticationService,
|
||||
public apiService: AlfrescoApiService,
|
||||
private logService: LogService,
|
||||
private sanitizer: DomSanitizer) {
|
||||
this.saveData = (function () {
|
||||
let a = document.createElement('a');
|
||||
document.body.appendChild(a);
|
||||
a.style.display = 'none';
|
||||
|
||||
return function (data, format, fileName) {
|
||||
let blob = null;
|
||||
|
||||
if (format === 'blob' || format === 'data') {
|
||||
blob = new Blob([data], { type: 'octet/stream' });
|
||||
}
|
||||
|
||||
if (format === 'object' || format === 'json') {
|
||||
let json = JSON.stringify(data);
|
||||
blob = new Blob([json], { type: 'octet/stream' });
|
||||
}
|
||||
|
||||
if (blob) {
|
||||
|
||||
if (typeof window.navigator !== 'undefined' && window.navigator.msSaveOrOpenBlob) {
|
||||
navigator.msSaveOrOpenBlob(blob, fileName);
|
||||
} else {
|
||||
let url = window.URL.createObjectURL(blob);
|
||||
a.href = url;
|
||||
a.download = fileName;
|
||||
a.click();
|
||||
|
||||
window.URL.revokeObjectURL(url);
|
||||
}
|
||||
}
|
||||
};
|
||||
}());
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes content download for a Blob with a file name.
|
||||
*
|
||||
* @param {Blob} blob Content to download.
|
||||
* @param {string} fileName Name of the resulting file.
|
||||
*
|
||||
* @memberOf ContentService
|
||||
*/
|
||||
downloadBlob(blob: Blob, fileName: string): void {
|
||||
this.saveData(blob, 'blob', fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes content download for a data array with a file name.
|
||||
*
|
||||
* @param {*} data Data to download.
|
||||
* @param {string} fileName Name of the resulting file.
|
||||
*
|
||||
* @memberOf ContentService
|
||||
*/
|
||||
downloadData(data: any, fileName: string): void {
|
||||
this.saveData(data, 'data', fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes content download for a JSON object with a file name.
|
||||
*
|
||||
* @param {*} json JSON object to download.
|
||||
* @param {any} fileName Name of the resulting file.
|
||||
*
|
||||
* @memberOf ContentService
|
||||
*/
|
||||
downloadJSON(json: any, fileName): void {
|
||||
this.saveData(json, 'json', fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a trusted object URL from the Blob.
|
||||
* WARNING: calling this method with untrusted user data exposes your application to XSS security risks!
|
||||
* @param {Blob} blob Data to wrap into object URL
|
||||
* @returns {string} Object URL content.
|
||||
*
|
||||
* @memberOf ContentService
|
||||
*/
|
||||
createTrustedUrl(blob: Blob): string {
|
||||
let url = window.URL.createObjectURL(blob);
|
||||
return <string> this.sanitizer.bypassSecurityTrustUrl(url);
|
||||
}
|
||||
|
||||
private get contentApi(): ContentApi {
|
||||
return this.apiService.getInstance().content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get thumbnail URL for the given document node.
|
||||
*
|
||||
* @param {string|MinimalNodeEntity} nodeId Node to get URL for.
|
||||
* @param {boolean} [attachment] Retrieve content as an attachment for download
|
||||
* @param {string} [ticket] Custom ticket to use for authentication
|
||||
* @returns {string} The URL address pointing to the content.
|
||||
*/
|
||||
getDocumentThumbnailUrl(nodeId: any, attachment?: boolean, ticket?: string): string {
|
||||
|
||||
if (nodeId && nodeId.entry) {
|
||||
nodeId = nodeId.entry.id;
|
||||
}
|
||||
|
||||
return this.contentApi.getDocumentThumbnailUrl(nodeId, attachment, ticket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content URL for the given node.
|
||||
*
|
||||
* @param nodeId {string|MinimalNodeEntity} Node to get URL for.
|
||||
* @param {boolean} [attachment] Retrieve content as an attachment for download
|
||||
* @param {string} [ticket] Custom ticket to use for authentication
|
||||
* @returns {string} The URL address pointing to the content.
|
||||
*/
|
||||
getContentUrl(nodeId: any, attachment?: boolean, ticket?: string): string {
|
||||
|
||||
if (nodeId && nodeId.entry) {
|
||||
nodeId = nodeId.entry.id;
|
||||
}
|
||||
|
||||
return this.contentApi.getContentUrl(nodeId, attachment, ticket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get content for the given node.
|
||||
* @param nodeId {string}.
|
||||
*
|
||||
* @returns {Observable<any>} URL address.
|
||||
*/
|
||||
getNodeContent(nodeId: string): Observable<any> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().core.nodesApi.getFileContent(nodeId).then((dataContent) => {
|
||||
return dataContent;
|
||||
})).catch(this.handleError);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a folder
|
||||
* @param name - the folder name
|
||||
*/
|
||||
createFolder(relativePath: string, name: string, parentId?: string): Observable<FolderCreatedEvent> {
|
||||
return Observable.fromPromise(this.apiService.getInstance().nodes.createFolder(name, relativePath, parentId))
|
||||
.do(data => {
|
||||
this.folderCreated.next(<FolderCreatedEvent> {
|
||||
relativePath: relativePath,
|
||||
name: name,
|
||||
parentId: parentId,
|
||||
node: data
|
||||
});
|
||||
})
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user has permissions on that node
|
||||
* @param MinimalNode - node to check allowableOperations
|
||||
* @param PermissionsEnum - create, delete, update, updatePermissions, !create, !delete, !update, !updatePermissions
|
||||
*
|
||||
* @returns {boolean} has permission
|
||||
*/
|
||||
hasPermission(node: any, permission: PermissionsEnum | string): boolean {
|
||||
let hasPermission = false;
|
||||
|
||||
if (this.hasAllowableOperations(node)) {
|
||||
if (permission && permission.startsWith('!')) {
|
||||
hasPermission = node.allowableOperations.find(currentPermission => currentPermission === permission.replace('!', '')) ? false : true;
|
||||
} else {
|
||||
hasPermission = node.allowableOperations.find(currentPermission => currentPermission === permission) ? true : false;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (permission && permission.startsWith('!')) {
|
||||
hasPermission = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hasPermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the node has the properties allowableOperations
|
||||
* @param MinimalNode - node to check allowableOperations
|
||||
*
|
||||
* @returns {boolean} has AllowableOperations
|
||||
*/
|
||||
hasAllowableOperations(node: any): boolean {
|
||||
return node && node.allowableOperations ? true : false;
|
||||
}
|
||||
|
||||
private handleError(error: any) {
|
||||
this.logService.error(error);
|
||||
return Observable.throw(error || 'Server error');
|
||||
}
|
||||
}
|
48
lib/core/services/cookie.service.ts
Normal file
48
lib/core/services/cookie.service.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class CookieService {
|
||||
|
||||
/**
|
||||
* Retrieve cookie by key.
|
||||
*
|
||||
* @returns {string | null}
|
||||
*/
|
||||
getItem(key: string): string | null {
|
||||
const regexp = new RegExp('(?:' + key + '|;\s*' + key + ')=(.*?)(?:;|$)', 'g');
|
||||
const result = regexp.exec(document.cookie);
|
||||
return (result === null) ? null : result[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cookie.
|
||||
* @param key
|
||||
* @param data
|
||||
* @param expiration
|
||||
* @param path
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
setItem(key: string, data: string, expiration: Date | null, path: string | null): void {
|
||||
document.cookie = `${key}=${data}` +
|
||||
(expiration ? ';expires=' + expiration.toUTCString() : '') +
|
||||
(path ? `;path=${path}` : ';path=/');
|
||||
}
|
||||
}
|
54
lib/core/services/deleted-nodes-api.service.ts
Normal file
54
lib/core/services/deleted-nodes-api.service.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
import { NodePaging } from 'alfresco-js-api';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
@Injectable()
|
||||
export class DeletedNodesApiService {
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService,
|
||||
private preferences: UserPreferencesService
|
||||
) {}
|
||||
|
||||
private get nodesApi() {
|
||||
return this.apiService.getInstance().core.nodesApi;
|
||||
}
|
||||
|
||||
getDeletedNodes(options?: Object): Observable<NodePaging> {
|
||||
const { nodesApi, handleError } = this;
|
||||
const defaultOptions = {
|
||||
include: [ 'path', 'properties' ],
|
||||
maxItems: this.preferences.paginationSize,
|
||||
skipCount: 0
|
||||
};
|
||||
const queryOptions = Object.assign(defaultOptions, options);
|
||||
const promise = nodesApi.getDeletedNodes(queryOptions);
|
||||
|
||||
return Observable
|
||||
.fromPromise(promise)
|
||||
.catch(handleError);
|
||||
}
|
||||
|
||||
private handleError(error: any): Observable<any> {
|
||||
return Observable.of(error);
|
||||
}
|
||||
}
|
193
lib/core/services/discovery-api.service.spec.ts
Normal file
193
lib/core/services/discovery-api.service.spec.ts
Normal file
@@ -0,0 +1,193 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, TestBed } from '@angular/core/testing';
|
||||
import { BpmProductVersionModel, EcmProductVersionModel } from '../models/product-version.model';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { AppConfigModule } from '../app-config/app-config.module';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { DiscoveryApiService } from './discovery-api.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
let fakeEcmDiscoveryResponse: any = {
|
||||
'entry': {
|
||||
'repository': {
|
||||
'edition': 'FAKE',
|
||||
'version': {
|
||||
'major': '5',
|
||||
'minor': '2',
|
||||
'patch': '0',
|
||||
'hotfix': '0',
|
||||
'schema': 999999,
|
||||
'label': 'r134899-b26',
|
||||
'display': '5.2.0.0 (r134899-b26) schema 10005'
|
||||
},
|
||||
'license': {
|
||||
'issuedAt': '2017-06-22T10:56:45.796+0000',
|
||||
'expiresAt': '2017-07-22T00:00:00.000+0000',
|
||||
'remainingDays': 4,
|
||||
'holder': 'Trial User',
|
||||
'mode': 'ENTERPRISE',
|
||||
'entitlements': {
|
||||
'isClusterEnabled': false,
|
||||
'isCryptodocEnabled': false
|
||||
}
|
||||
},
|
||||
'status': {
|
||||
'isReadOnly': false,
|
||||
'isAuditEnabled': true,
|
||||
'isQuickShareEnabled': true,
|
||||
'isThumbnailGenerationEnabled': true
|
||||
},
|
||||
'modules': [
|
||||
{
|
||||
'id': 'alfresco-fake-services',
|
||||
'title': 'Alfresco Share Services AMP',
|
||||
'description': 'Module to be applied to alfresco.war, containing APIs for Alfresco Share',
|
||||
'version': '5.2.0',
|
||||
'installDate': '2017-03-07T08:48:14.161+0000',
|
||||
'installState': 'INSTALLED',
|
||||
'versionMin': '5.1',
|
||||
'versionMax': '999'
|
||||
},
|
||||
{
|
||||
'id': 'alfresco-trashcan-fake',
|
||||
'title': 'alfresco-trashcan-cleaner project',
|
||||
'description': 'The Alfresco Trash Can Cleaner (Alfresco Module)',
|
||||
'version': '2.2',
|
||||
'installState': 'UNKNOWN',
|
||||
'versionMin': '0',
|
||||
'versionMax': '999'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let fakeBPMDiscoveryResponse: any = {
|
||||
'revisionVersion': '2',
|
||||
'edition': 'SUPER FAKE EDITION',
|
||||
'type': 'bpmSuite',
|
||||
'majorVersion': '1',
|
||||
'minorVersion': '6'
|
||||
};
|
||||
|
||||
describe('Discovery Api Service', () => {
|
||||
|
||||
let service;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppConfigModule
|
||||
],
|
||||
providers: [
|
||||
DiscoveryApiService,
|
||||
AlfrescoApiService,
|
||||
UserPreferencesService,
|
||||
AuthenticationService,
|
||||
SettingsService,
|
||||
StorageService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
let appConfig: AppConfigService = TestBed.get(AppConfigService);
|
||||
appConfig.config = {
|
||||
ecmHost: 'http://localhost:9876/ecm'
|
||||
};
|
||||
service = TestBed.get(DiscoveryApiService);
|
||||
jasmine.Ajax.install();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
describe('For ECM', () => {
|
||||
it('Should retrieve the info about the product for ECM', (done) => {
|
||||
service.getEcmProductInfo().subscribe((data: EcmProductVersionModel) => {
|
||||
expect(data).not.toBeNull();
|
||||
expect(data.edition).toBe('FAKE');
|
||||
expect(data.version.schema).toBe(999999);
|
||||
expect(data.license.isClusterEnabled).toBeFalsy();
|
||||
expect(data.status.isQuickShareEnabled).toBeTruthy();
|
||||
expect(data.modules.length).toBe(2);
|
||||
expect(data.modules[0].id).toBe('alfresco-fake-services');
|
||||
expect(data.modules[1].id).toBe('alfresco-trashcan-fake');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: fakeEcmDiscoveryResponse
|
||||
});
|
||||
});
|
||||
|
||||
it('getEcmProductInfo catch errors call', (done) => {
|
||||
service.getEcmProductInfo().subscribe(
|
||||
() => {
|
||||
},
|
||||
() => {
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 403
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('For BPM', () => {
|
||||
it('Should retrieve the info about the product for BPM', (done) => {
|
||||
service.getBpmProductInfo().subscribe((data: BpmProductVersionModel) => {
|
||||
expect(data).not.toBeNull();
|
||||
expect(data.edition).toBe('SUPER FAKE EDITION');
|
||||
expect(data.revisionVersion).toBe('2');
|
||||
expect(data.type).toBe('bpmSuite');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: fakeBPMDiscoveryResponse
|
||||
});
|
||||
});
|
||||
|
||||
it('getBpmProductInfo catch errors call', (done) => {
|
||||
service.getBpmProductInfo().subscribe(
|
||||
() => {
|
||||
},
|
||||
() => {
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 403
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
45
lib/core/services/discovery-api.service.ts
Normal file
45
lib/core/services/discovery-api.service.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { BpmProductVersionModel, EcmProductVersionModel } from '../models/product-version.model';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
|
||||
@Injectable()
|
||||
export class DiscoveryApiService {
|
||||
|
||||
constructor(private apiService: AlfrescoApiService) { }
|
||||
|
||||
public getEcmProductInfo() {
|
||||
return Observable.fromPromise(
|
||||
this.apiService.getInstance().discovery.discoveryApi.getRepositoryInformation())
|
||||
.map(res => new EcmProductVersionModel(res))
|
||||
.catch(this.handleError);
|
||||
}
|
||||
|
||||
public getBpmProductInfo() {
|
||||
return Observable.fromPromise(
|
||||
this.apiService.getInstance().activiti.aboutApi.getAppVersion())
|
||||
.map(res => new BpmProductVersionModel(res))
|
||||
.catch(this.handleError);
|
||||
}
|
||||
|
||||
private handleError(error): Observable<any> {
|
||||
return Observable.throw(error);
|
||||
}
|
||||
}
|
66
lib/core/services/dynamic-component-mapper.service.ts
Normal file
66
lib/core/services/dynamic-component-mapper.service.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Type } from '@angular/core';
|
||||
|
||||
export interface DynamicComponentModel { type: string; }
|
||||
export type DynamicComponentResolveFunction = (model: DynamicComponentModel) => Type<{}>;
|
||||
export class DynamicComponentResolver {
|
||||
static fromType(type: Type<{}>): DynamicComponentResolveFunction {
|
||||
return (model: DynamicComponentModel) => {
|
||||
return type;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export abstract class DynamicComponentMapper {
|
||||
|
||||
protected defaultValue: Type<{}> = undefined;
|
||||
protected types: { [key: string]: DynamicComponentResolveFunction } = {};
|
||||
|
||||
getComponentTypeResolver(type: string, defaultValue: Type<{}> = this.defaultValue): DynamicComponentResolveFunction {
|
||||
if (type) {
|
||||
return this.types[type] || DynamicComponentResolver.fromType(defaultValue);
|
||||
}
|
||||
return DynamicComponentResolver.fromType(defaultValue);
|
||||
}
|
||||
|
||||
setComponentTypeResolver(type: string, resolver: DynamicComponentResolveFunction, override: boolean = false) {
|
||||
if (!type) {
|
||||
throw new Error(`type is null or not defined`);
|
||||
}
|
||||
|
||||
if (!resolver) {
|
||||
throw new Error(`resolver is null or not defined`);
|
||||
}
|
||||
|
||||
let existing = this.types[type];
|
||||
if (existing && !override) {
|
||||
throw new Error(`already mapped, use override option if you intend replacing existing mapping.`);
|
||||
}
|
||||
|
||||
this.types[type] = resolver;
|
||||
}
|
||||
|
||||
resolveComponentType(model: DynamicComponentModel, defaultValue: Type<{}> = this.defaultValue): Type<{}> {
|
||||
if (model) {
|
||||
let resolver = this.getComponentTypeResolver(model.type, defaultValue);
|
||||
return resolver(model);
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
85
lib/core/services/favorites-api.service.ts
Normal file
85
lib/core/services/favorites-api.service.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { NodePaging } from 'alfresco-js-api';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
@Injectable()
|
||||
export class FavoritesApiService {
|
||||
static remapFavoritesData(data: any = {}): NodePaging {
|
||||
const list = (data.list || {});
|
||||
const pagination = (list.pagination || {});
|
||||
const entries: any[] = FavoritesApiService
|
||||
.remapFavoriteEntries(list.entries || []);
|
||||
|
||||
return <NodePaging> {
|
||||
list: { entries, pagination }
|
||||
};
|
||||
}
|
||||
|
||||
static remapEntry({ entry }: any): any {
|
||||
entry.properties = {
|
||||
'cm:title': entry.title,
|
||||
'cm:description': entry.description
|
||||
};
|
||||
|
||||
return { entry };
|
||||
}
|
||||
|
||||
static remapFavoriteEntries(entries: any[]) {
|
||||
return entries
|
||||
.map(({ entry: { target }}: any) => ({
|
||||
entry: target.file || target.folder
|
||||
}))
|
||||
.filter(({ entry }) => (!!entry))
|
||||
.map(FavoritesApiService.remapEntry);
|
||||
}
|
||||
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService,
|
||||
private preferences: UserPreferencesService
|
||||
) {}
|
||||
|
||||
private get favoritesApi() {
|
||||
return this.apiService.getInstance().core.favoritesApi;
|
||||
}
|
||||
|
||||
getFavorites(personId: string, options?: any): Observable<NodePaging> {
|
||||
const { favoritesApi, handleError } = this;
|
||||
const defaultOptions = {
|
||||
maxItems: this.preferences.paginationSize,
|
||||
skipCount: 0,
|
||||
where: '(EXISTS(target/file) OR EXISTS(target/folder))',
|
||||
include: [ 'properties', 'allowableOperations' ]
|
||||
};
|
||||
const queryOptions = Object.assign(defaultOptions, options);
|
||||
const promise = favoritesApi
|
||||
.getFavorites(personId, queryOptions)
|
||||
.then(FavoritesApiService.remapFavoritesData);
|
||||
|
||||
return Observable
|
||||
.fromPromise(promise)
|
||||
.catch(handleError);
|
||||
}
|
||||
|
||||
private handleError(error): Observable<any> {
|
||||
return Observable.of(error);
|
||||
}
|
||||
}
|
44
lib/core/services/highlight-transform.service.ts
Normal file
44
lib/core/services/highlight-transform.service.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
export interface HightlightTransformResult {
|
||||
text: string;
|
||||
changed: boolean;
|
||||
}
|
||||
export class HighlightTransformService {
|
||||
|
||||
public highlight(text: string, search: string, wrapperClass: string = 'highlight'): HightlightTransformResult {
|
||||
let isMatching = false,
|
||||
result = text;
|
||||
|
||||
if (search && text) {
|
||||
let pattern = search.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
|
||||
pattern = pattern.split(' ').filter((t) => {
|
||||
return t.length > 0;
|
||||
}).join('|');
|
||||
|
||||
const regex = new RegExp(pattern, 'gi');
|
||||
result = text.replace(regex, (match) => {
|
||||
isMatching = true;
|
||||
return `<span class="${wrapperClass}">${match}</span>`;
|
||||
});
|
||||
return { text: result, changed: isMatching};
|
||||
} else {
|
||||
return { text: result, changed: isMatching};
|
||||
}
|
||||
}
|
||||
}
|
18
lib/core/services/index.ts
Normal file
18
lib/core/services/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
export * from './public-api';
|
181
lib/core/services/log.service.spec.ts
Normal file
181
lib/core/services/log.service.spec.ts
Normal file
@@ -0,0 +1,181 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { HttpClientModule } from '@angular/common/http';
|
||||
import { Component } from '@angular/core';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { LogService } from './log.service';
|
||||
|
||||
describe('Log Service', () => {
|
||||
|
||||
let providesLogComponent: ComponentFixture<ProvidesLogComponent>;
|
||||
let appConfigService: AppConfigService;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
HttpClientModule
|
||||
],
|
||||
declarations: [ProvidesLogComponent],
|
||||
providers: [
|
||||
LogService,
|
||||
AppConfigService
|
||||
]
|
||||
});
|
||||
|
||||
TestBed.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
appConfigService = TestBed.get(AppConfigService);
|
||||
});
|
||||
|
||||
it('should not log anything if is silent', () => {
|
||||
appConfigService.config['logLevel'] = 'silent';
|
||||
providesLogComponent = TestBed.createComponent(ProvidesLogComponent);
|
||||
|
||||
spyOn(console, 'log');
|
||||
spyOn(console, 'trace');
|
||||
spyOn(console, 'debug');
|
||||
spyOn(console, 'info');
|
||||
spyOn(console, 'warn');
|
||||
spyOn(console, 'error');
|
||||
|
||||
providesLogComponent.componentInstance.log();
|
||||
providesLogComponent.componentInstance.trace();
|
||||
providesLogComponent.componentInstance.debug();
|
||||
providesLogComponent.componentInstance.info();
|
||||
providesLogComponent.componentInstance.warn();
|
||||
providesLogComponent.componentInstance.error();
|
||||
|
||||
expect(console.log).not.toHaveBeenCalled();
|
||||
expect(console.trace).not.toHaveBeenCalled();
|
||||
expect(console.debug).not.toHaveBeenCalled();
|
||||
expect(console.info).not.toHaveBeenCalled();
|
||||
expect(console.warn).not.toHaveBeenCalled();
|
||||
expect(console.error).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should log only warning and errors if is warning level', () => {
|
||||
appConfigService.config['logLevel'] = 'WARN';
|
||||
providesLogComponent = TestBed.createComponent(ProvidesLogComponent);
|
||||
|
||||
spyOn(console, 'log');
|
||||
spyOn(console, 'error');
|
||||
spyOn(console, 'trace');
|
||||
spyOn(console, 'warn');
|
||||
|
||||
providesLogComponent.componentInstance.log();
|
||||
providesLogComponent.componentInstance.error();
|
||||
providesLogComponent.componentInstance.trace();
|
||||
providesLogComponent.componentInstance.warn();
|
||||
|
||||
expect(console.log).not.toHaveBeenCalled();
|
||||
expect(console.error).toHaveBeenCalled();
|
||||
expect(console.warn).toHaveBeenCalled();
|
||||
expect(console.trace).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should debug level not log trace and log', () => {
|
||||
appConfigService.config['logLevel'] = 'debug';
|
||||
providesLogComponent = TestBed.createComponent(ProvidesLogComponent);
|
||||
|
||||
spyOn(console, 'log');
|
||||
spyOn(console, 'trace');
|
||||
spyOn(console, 'debug');
|
||||
spyOn(console, 'info');
|
||||
spyOn(console, 'warn');
|
||||
spyOn(console, 'error');
|
||||
|
||||
providesLogComponent.componentInstance.log();
|
||||
providesLogComponent.componentInstance.trace();
|
||||
providesLogComponent.componentInstance.debug();
|
||||
providesLogComponent.componentInstance.info();
|
||||
providesLogComponent.componentInstance.warn();
|
||||
providesLogComponent.componentInstance.error();
|
||||
|
||||
expect(console.log).not.toHaveBeenCalled();
|
||||
expect(console.trace).not.toHaveBeenCalled();
|
||||
expect(console.debug).toHaveBeenCalled();
|
||||
expect(console.info).toHaveBeenCalled();
|
||||
expect(console.warn).toHaveBeenCalled();
|
||||
expect(console.error).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should trace level log all', () => {
|
||||
appConfigService.config['logLevel'] = 'trace';
|
||||
providesLogComponent = TestBed.createComponent(ProvidesLogComponent);
|
||||
|
||||
spyOn(console, 'log');
|
||||
spyOn(console, 'trace');
|
||||
spyOn(console, 'debug');
|
||||
spyOn(console, 'info');
|
||||
spyOn(console, 'warn');
|
||||
spyOn(console, 'error');
|
||||
|
||||
providesLogComponent.componentInstance.log();
|
||||
providesLogComponent.componentInstance.trace();
|
||||
providesLogComponent.componentInstance.debug();
|
||||
providesLogComponent.componentInstance.info();
|
||||
providesLogComponent.componentInstance.warn();
|
||||
providesLogComponent.componentInstance.error();
|
||||
|
||||
expect(console.log).toHaveBeenCalled();
|
||||
expect(console.trace).toHaveBeenCalled();
|
||||
expect(console.debug).toHaveBeenCalled();
|
||||
expect(console.info).toHaveBeenCalled();
|
||||
expect(console.warn).toHaveBeenCalled();
|
||||
expect(console.error).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@Component({
|
||||
template: '',
|
||||
providers: [LogService]
|
||||
})
|
||||
class ProvidesLogComponent {
|
||||
constructor(public logService: LogService) {
|
||||
|
||||
}
|
||||
|
||||
error() {
|
||||
this.logService.error('Test message');
|
||||
}
|
||||
|
||||
info() {
|
||||
this.logService.info('Test message');
|
||||
}
|
||||
|
||||
warn() {
|
||||
this.logService.warn('Test message');
|
||||
}
|
||||
|
||||
log() {
|
||||
this.logService.log('Test message');
|
||||
}
|
||||
|
||||
debug() {
|
||||
this.logService.debug('Test message');
|
||||
}
|
||||
|
||||
trace() {
|
||||
this.logService.trace('Test message');
|
||||
}
|
||||
|
||||
}
|
122
lib/core/services/log.service.ts
Normal file
122
lib/core/services/log.service.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { logLevels, LogLevelsEnum } from '../models/log-levels.model';
|
||||
|
||||
@Injectable()
|
||||
export class LogService {
|
||||
|
||||
currentLogLevel: LogLevelsEnum = LogLevelsEnum.TRACE;
|
||||
|
||||
constructor(appConfig: AppConfigService) {
|
||||
if (appConfig) {
|
||||
let configLevel: string = appConfig.get<string>('logLevel');
|
||||
|
||||
if (configLevel) {
|
||||
this.currentLogLevel = this.getCurrentLogLevel(configLevel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get error(): (message?: any, ...optionalParams: any[]) => any {
|
||||
if (this.currentLogLevel >= LogLevelsEnum.ERROR) {
|
||||
return console.error.bind(console);
|
||||
}
|
||||
return (message?: any, ...optionalParams: any[]) => {
|
||||
};
|
||||
}
|
||||
|
||||
get debug(): (message?: any, ...optionalParams: any[]) => any {
|
||||
if (this.currentLogLevel >= LogLevelsEnum.DEBUG) {
|
||||
return console.debug.bind(console);
|
||||
}
|
||||
return (message?: any, ...optionalParams: any[]) => {
|
||||
};
|
||||
}
|
||||
|
||||
get info(): (message?: any, ...optionalParams: any[]) => any {
|
||||
if (this.currentLogLevel >= LogLevelsEnum.INFO) {
|
||||
return console.info.bind(console);
|
||||
}
|
||||
return (message?: any, ...optionalParams: any[]) => {
|
||||
};
|
||||
}
|
||||
|
||||
get log(): (message?: any, ...optionalParams: any[]) => any {
|
||||
if (this.currentLogLevel >= LogLevelsEnum.TRACE) {
|
||||
return console.log.bind(console);
|
||||
}
|
||||
|
||||
return (message?: any, ...optionalParams: any[]) => {
|
||||
};
|
||||
}
|
||||
|
||||
get trace(): (message?: any, ...optionalParams: any[]) => any {
|
||||
if (this.currentLogLevel >= LogLevelsEnum.TRACE) {
|
||||
return console.trace.bind(console);
|
||||
}
|
||||
return (message?: any, ...optionalParams: any[]) => {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
get warn(): (message?: any, ...optionalParams: any[]) => any {
|
||||
if (this.currentLogLevel >= LogLevelsEnum.WARN) {
|
||||
return console.warn.bind(console);
|
||||
}
|
||||
return (message?: any, ...optionalParams: any[]) => {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
get assert(): (message?: any, ...optionalParams: any[]) => any {
|
||||
if (this.currentLogLevel !== LogLevelsEnum.SILENT) {
|
||||
return console.assert.bind(console);
|
||||
}
|
||||
return (message?: any, ...optionalParams: any[]) => {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
get group(): (message?: any, ...optionalParams: any[]) => any {
|
||||
if (this.currentLogLevel !== LogLevelsEnum.SILENT) {
|
||||
return console.group.bind(console);
|
||||
}
|
||||
return (message?: any, ...optionalParams: any[]) => {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
get groupEnd(): (message?: any, ...optionalParams: any[]) => any {
|
||||
if (this.currentLogLevel !== LogLevelsEnum.SILENT) {
|
||||
return console.groupEnd.bind(console);
|
||||
}
|
||||
return (message?: any, ...optionalParams: any[]) => {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
getCurrentLogLevel(level: string): LogLevelsEnum {
|
||||
let referencedLevel = logLevels.find((currentLevel: any) => {
|
||||
return currentLevel.name.toLocaleLowerCase() === level.toLocaleLowerCase();
|
||||
});
|
||||
|
||||
return referencedLevel ? referencedLevel.level : 5;
|
||||
}
|
||||
}
|
117
lib/core/services/nodes-api.service.ts
Normal file
117
lib/core/services/nodes-api.service.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { MinimalNodeEntity, MinimalNodeEntryEntity, NodePaging } from 'alfresco-js-api';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
@Injectable()
|
||||
export class NodesApiService {
|
||||
|
||||
constructor(
|
||||
private api: AlfrescoApiService,
|
||||
private preferences: UserPreferencesService) {}
|
||||
|
||||
private get nodesApi() {
|
||||
return this.api.getInstance().core.nodesApi;
|
||||
}
|
||||
|
||||
private getEntryFromEntity(entity: MinimalNodeEntity) {
|
||||
return entity.entry;
|
||||
}
|
||||
|
||||
getNode(nodeId: string, options: any = {}): Observable<MinimalNodeEntryEntity> {
|
||||
const { nodesApi, handleError, getEntryFromEntity } = this;
|
||||
const defaults = {
|
||||
include: [ 'path', 'properties', 'allowableOperations' ]
|
||||
};
|
||||
const queryOptions = Object.assign(defaults, options);
|
||||
const promise = nodesApi
|
||||
.getNode(nodeId, queryOptions)
|
||||
.then(getEntryFromEntity);
|
||||
|
||||
return Observable
|
||||
.fromPromise(promise)
|
||||
.catch(handleError);
|
||||
}
|
||||
|
||||
getNodeChildren(nodeId: string, options: any = {}): Observable<NodePaging> {
|
||||
const { nodesApi, handleError } = this;
|
||||
const defaults = {
|
||||
maxItems: this.preferences.paginationSize,
|
||||
skipCount: 0,
|
||||
include: [ 'path', 'properties', 'allowableOperations' ]
|
||||
};
|
||||
const queryOptions = Object.assign(defaults, options);
|
||||
const promise = nodesApi
|
||||
.getNodeChildren(nodeId, queryOptions);
|
||||
|
||||
return Observable
|
||||
.fromPromise(promise)
|
||||
.catch(handleError);
|
||||
}
|
||||
|
||||
createNode(parentNodeId: string, nodeBody: any, options: any = {}): Observable<MinimalNodeEntryEntity> {
|
||||
const { nodesApi, handleError, getEntryFromEntity } = this;
|
||||
const promise = nodesApi
|
||||
.addNode(parentNodeId, nodeBody, options)
|
||||
.then(getEntryFromEntity);
|
||||
|
||||
return Observable.fromPromise(promise).catch(handleError);
|
||||
}
|
||||
|
||||
createFolder(parentNodeId: string, nodeBody: any, options: any = {}): Observable<MinimalNodeEntryEntity> {
|
||||
const body = Object.assign({ nodeType: 'cm:folder' }, nodeBody);
|
||||
return this.createNode(parentNodeId, body, options);
|
||||
}
|
||||
|
||||
updateNode(nodeId: string, nodeBody: any, options: any = {}): Observable<MinimalNodeEntryEntity> {
|
||||
const { nodesApi, handleError, getEntryFromEntity } = this;
|
||||
const promise = nodesApi
|
||||
.updateNode(nodeId, nodeBody, options)
|
||||
.then(getEntryFromEntity);
|
||||
|
||||
return Observable.fromPromise(promise).catch(handleError);
|
||||
}
|
||||
|
||||
deleteNode(nodeId: string, options: any = {}): Observable<void> {
|
||||
const { nodesApi, handleError } = this;
|
||||
const promise = nodesApi
|
||||
.deleteNode(nodeId, options);
|
||||
|
||||
return Observable
|
||||
.fromPromise(promise)
|
||||
.catch(handleError);
|
||||
}
|
||||
|
||||
restoreNode(nodeId: string): Observable<MinimalNodeEntryEntity> {
|
||||
const { nodesApi, handleError, getEntryFromEntity } = this;
|
||||
const promise = nodesApi
|
||||
.restoreNode(nodeId)
|
||||
.then(getEntryFromEntity);
|
||||
|
||||
return Observable
|
||||
.fromPromise(promise)
|
||||
.catch(handleError);
|
||||
}
|
||||
|
||||
handleError(error: any): Observable<any> {
|
||||
return Observable.throw(error);
|
||||
}
|
||||
}
|
97
lib/core/services/notification.service.spec.ts
Normal file
97
lib/core/services/notification.service.spec.ts
Normal file
@@ -0,0 +1,97 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { LiveAnnouncer } from '@angular/cdk/a11y';
|
||||
import { OVERLAY_PROVIDERS, OverlayModule } from '@angular/cdk/overlay';
|
||||
import { Component } from '@angular/core';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MatSnackBar, MatSnackBarModule } from '@angular/material';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { NotificationService } from './notification.service';
|
||||
|
||||
describe('NotificationService', () => {
|
||||
let fixture: ComponentFixture<ProvidesNotificationServiceComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
BrowserAnimationsModule,
|
||||
OverlayModule,
|
||||
MatSnackBarModule
|
||||
],
|
||||
declarations: [ProvidesNotificationServiceComponent],
|
||||
providers: [
|
||||
NotificationService,
|
||||
MatSnackBar,
|
||||
OVERLAY_PROVIDERS,
|
||||
LiveAnnouncer
|
||||
]
|
||||
});
|
||||
|
||||
TestBed.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ProvidesNotificationServiceComponent);
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
xit('should open a message notification bar', (done) => {
|
||||
let promise = fixture.componentInstance.sendMessage();
|
||||
promise.afterDismissed().subscribe(() => {
|
||||
done();
|
||||
});
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(document.querySelector('snack-bar-container')).not.toBeNull();
|
||||
});
|
||||
|
||||
xit('should open a message notification bar with action', (done) => {
|
||||
let promise = fixture.componentInstance.sendMessageAction();
|
||||
promise.afterDismissed().subscribe(() => {
|
||||
done();
|
||||
});
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(document.querySelector('snack-bar-container')).not.toBeNull();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@Component({
|
||||
template: '',
|
||||
providers: [NotificationService]
|
||||
})
|
||||
class ProvidesNotificationServiceComponent {
|
||||
constructor(public notificationService: NotificationService) {
|
||||
|
||||
}
|
||||
|
||||
sendMessage() {
|
||||
let promise = this.notificationService.openSnackMessage('Test notification', 5000);
|
||||
return promise;
|
||||
}
|
||||
|
||||
sendMessageAction() {
|
||||
let promise = this.notificationService.openSnackMessageAction('Test notification', 'TestWarn', 5000);
|
||||
return promise;
|
||||
}
|
||||
|
||||
}
|
40
lib/core/services/notification.service.ts
Normal file
40
lib/core/services/notification.service.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { MatSnackBar, MatSnackBarRef } from '@angular/material';
|
||||
|
||||
@Injectable()
|
||||
export class NotificationService {
|
||||
|
||||
static DEFAULT_DURATION_MESSAGE: number = 5000;
|
||||
|
||||
constructor(public snackbar: MatSnackBar) {
|
||||
}
|
||||
|
||||
public openSnackMessage(message: string, millisecondsDuration?: number): MatSnackBarRef<any> {
|
||||
return this.snackbar.open(message, null, {
|
||||
duration: millisecondsDuration || NotificationService.DEFAULT_DURATION_MESSAGE
|
||||
});
|
||||
}
|
||||
|
||||
public openSnackMessageAction(message: string, action: string, millisecondsDuration?: number): MatSnackBarRef<any> {
|
||||
return this.snackbar.open(message, action, {
|
||||
duration: millisecondsDuration || NotificationService.DEFAULT_DURATION_MESSAGE
|
||||
});
|
||||
}
|
||||
}
|
100
lib/core/services/page-title.service.spec.ts
Normal file
100
lib/core/services/page-title.service.spec.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { inject, TestBed } from '@angular/core/testing';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
|
||||
import { AppConfigService } from '../app-config';
|
||||
import { PageTitleService } from './page-title.service';
|
||||
|
||||
class TestConfig {
|
||||
private setup: any = {
|
||||
applicationName: undefined
|
||||
};
|
||||
|
||||
titleService: Title = null;
|
||||
appTitleService: PageTitleService = null;
|
||||
|
||||
constructor(setup: any = {}) {
|
||||
Object.assign(this.setup, setup);
|
||||
|
||||
const titleServiceProvider = {
|
||||
provide: Title,
|
||||
useValue: {
|
||||
setTitle: jasmine.createSpy('setTitleSpy')
|
||||
}
|
||||
};
|
||||
|
||||
const appConfigProvider = {
|
||||
provide: AppConfigService,
|
||||
useValue: {
|
||||
config: {
|
||||
application: {
|
||||
name: this.setup.applicationName
|
||||
}
|
||||
},
|
||||
get: () => this.setup.applicationName,
|
||||
load: () => {}
|
||||
}
|
||||
};
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
titleServiceProvider,
|
||||
appConfigProvider,
|
||||
PageTitleService
|
||||
]
|
||||
});
|
||||
|
||||
inject([ Title, PageTitleService ], (titleService, appTitleService) => {
|
||||
this.titleService = titleService;
|
||||
this.appTitleService = appTitleService;
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
describe('AppTitle service', () => {
|
||||
it('sets default application name', () => {
|
||||
const { appTitleService, titleService } = new TestConfig({
|
||||
applicationName: undefined
|
||||
});
|
||||
|
||||
appTitleService.setTitle();
|
||||
expect(titleService.setTitle)
|
||||
.toHaveBeenCalledWith('Alfresco ADF Application');
|
||||
});
|
||||
|
||||
it('sets only the application name', () => {
|
||||
const { appTitleService, titleService } = new TestConfig({
|
||||
applicationName: 'My application'
|
||||
});
|
||||
|
||||
appTitleService.setTitle();
|
||||
expect(titleService.setTitle)
|
||||
.toHaveBeenCalledWith('My application');
|
||||
});
|
||||
|
||||
it('appends application name to the title', () => {
|
||||
const { appTitleService, titleService } = new TestConfig({
|
||||
applicationName: 'My application'
|
||||
});
|
||||
|
||||
appTitleService.setTitle('My page');
|
||||
expect(titleService.setTitle)
|
||||
.toHaveBeenCalledWith('My page - My application');
|
||||
});
|
||||
});
|
35
lib/core/services/page-title.service.ts
Normal file
35
lib/core/services/page-title.service.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
|
||||
@Injectable()
|
||||
export class PageTitleService {
|
||||
|
||||
constructor(
|
||||
private titleService: Title,
|
||||
private appConfig: AppConfigService) {}
|
||||
|
||||
setTitle(value: string = '') {
|
||||
const name = this.appConfig.get('application.name') || 'Alfresco ADF Application';
|
||||
const title = value ? `${value} - ${name}` : `${name}`;
|
||||
|
||||
this.titleService.setTitle(title);
|
||||
}
|
||||
}
|
114
lib/core/services/people-content.service.spec.ts
Normal file
114
lib/core/services/people-content.service.spec.ts
Normal file
@@ -0,0 +1,114 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, inject, TestBed } from '@angular/core/testing';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { PeopleContentService } from './people-content.service';
|
||||
|
||||
class PeopleContentServiceTest {
|
||||
service: any = null;
|
||||
setup: any = {
|
||||
rejectGetPerson: false
|
||||
};
|
||||
|
||||
constructor(setup: any = {}) {
|
||||
Object.assign(this.setup, setup);
|
||||
|
||||
const { alfrescoApiServiceMock } = this;
|
||||
|
||||
const alfrescoApiServiceProvider = {
|
||||
provide: AlfrescoApiService,
|
||||
useValue: alfrescoApiServiceMock
|
||||
};
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
alfrescoApiServiceProvider,
|
||||
PeopleContentService
|
||||
]
|
||||
});
|
||||
|
||||
inject([ PeopleContentService ], (service) => {
|
||||
this.service = service;
|
||||
})();
|
||||
}
|
||||
|
||||
private get alfrescoApiServiceMock(): any {
|
||||
const { setup } = this;
|
||||
|
||||
const peopleApiMock = {
|
||||
getPerson: jasmine.createSpy('getPersonSpy').and.callFake((personId) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
setup.rejectGetPerson
|
||||
? reject()
|
||||
: resolve({ id: personId });
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
return {
|
||||
getInstance: () => {
|
||||
return {
|
||||
core: { peopleApi: peopleApiMock }
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
get peopleApiGetPersonSpy() {
|
||||
return this.service.peopleApi.getPerson;
|
||||
}
|
||||
|
||||
get peopleApiGetPersonArguments() {
|
||||
return this.peopleApiGetPersonSpy.calls.mostRecent().args;
|
||||
}
|
||||
}
|
||||
|
||||
describe('PeopleAPI', () => {
|
||||
describe('Get persons', () => {
|
||||
it('calls method by an id', async(() => {
|
||||
const test = new PeopleContentServiceTest();
|
||||
|
||||
test.service.getPerson('person-1').subscribe(() => {
|
||||
expect(test.peopleApiGetPersonArguments[0])
|
||||
.toBe('person-1');
|
||||
});
|
||||
}));
|
||||
|
||||
it('calls method with "-me-"', async(() => {
|
||||
const test = new PeopleContentServiceTest();
|
||||
|
||||
test.service.getCurrentPerson().subscribe(() => {
|
||||
expect(test.peopleApiGetPersonArguments[0])
|
||||
.toBe('-me-');
|
||||
});
|
||||
}));
|
||||
|
||||
it('handles the error when it fails', async(() => {
|
||||
const test = new PeopleContentServiceTest({
|
||||
rejectGetPerson: true
|
||||
});
|
||||
|
||||
const handleErrorSpy = spyOn(test.service, 'handleError')
|
||||
.and.callThrough();
|
||||
|
||||
test.service.getPerson().subscribe(() => {
|
||||
expect(handleErrorSpy).toHaveBeenCalled();
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
47
lib/core/services/people-content.service.ts
Normal file
47
lib/core/services/people-content.service.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
|
||||
@Injectable()
|
||||
export class PeopleContentService {
|
||||
|
||||
constructor(private apiService: AlfrescoApiService) {}
|
||||
|
||||
private get peopleApi() {
|
||||
return this.apiService.getInstance().core.peopleApi;
|
||||
}
|
||||
|
||||
getPerson(personId: string): Observable<any> {
|
||||
const { peopleApi, handleError } = this;
|
||||
const promise = peopleApi.getPerson(personId);
|
||||
|
||||
return Observable
|
||||
.fromPromise(promise)
|
||||
.catch(handleError);
|
||||
}
|
||||
|
||||
getCurrentPerson(): Observable<any> {
|
||||
return this.getPerson('-me-');
|
||||
}
|
||||
|
||||
private handleError(error): Observable<any> {
|
||||
return Observable.of(error);
|
||||
}
|
||||
}
|
183
lib/core/services/people-process.service.spec.ts
Normal file
183
lib/core/services/people-process.service.spec.ts
Normal file
@@ -0,0 +1,183 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { UserProcessModel } from '../models';
|
||||
import { AppConfigServiceMock } from '../mock/app-config.service.mock';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { LogService } from './log.service';
|
||||
import { PeopleProcessService } from './people-process.service';
|
||||
import { StorageService } from './storage.service';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
const firstInvolvedUser: UserProcessModel = new UserProcessModel({
|
||||
id: 1,
|
||||
email: 'fake-user1@fake.com',
|
||||
firstName: 'fakeName1',
|
||||
lastName: 'fakeLast1'
|
||||
});
|
||||
|
||||
const secondInvolvedUser: UserProcessModel = new UserProcessModel({
|
||||
id: 2,
|
||||
email: 'fake-user2@fake.com',
|
||||
firstName: 'fakeName2',
|
||||
lastName: 'fakeLast2'
|
||||
});
|
||||
|
||||
const fakeInvolveUserList: UserProcessModel[] = [firstInvolvedUser, secondInvolvedUser];
|
||||
|
||||
describe('PeopleProcessService', () => {
|
||||
|
||||
let service: PeopleProcessService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
PeopleProcessService,
|
||||
AlfrescoApiService,
|
||||
StorageService,
|
||||
LogService,
|
||||
{ provide: AppConfigService, useClass: AppConfigServiceMock }
|
||||
]
|
||||
});
|
||||
service = TestBed.get(PeopleProcessService);
|
||||
});
|
||||
|
||||
describe('when user is logged in', () => {
|
||||
|
||||
beforeEach(() => {
|
||||
jasmine.Ajax.install();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
it('should be able to retrieve people to involve in the task', (done) => {
|
||||
service.getWorkflowUsers('fake-task-id', 'fake-filter').subscribe(
|
||||
(users: UserProcessModel[]) => {
|
||||
expect(users).toBeDefined();
|
||||
expect(users.length).toBe(2);
|
||||
expect(users[0].id).toEqual(1);
|
||||
expect(users[0].email).toEqual('fake-user1@fake.com');
|
||||
expect(users[0].firstName).toEqual('fakeName1');
|
||||
expect(users[0].lastName).toEqual('fakeLast1');
|
||||
done();
|
||||
});
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: {data: fakeInvolveUserList}
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to get people images for people retrieved', (done) => {
|
||||
service.getWorkflowUsers('fake-task-id', 'fake-filter').subscribe(
|
||||
(users: UserProcessModel[]) => {
|
||||
expect(users).toBeDefined();
|
||||
expect(users.length).toBe(2);
|
||||
expect(service.getUserImage(users[0])).toContain('/users/' + users[0].id + '/picture');
|
||||
expect(service.getUserImage(users[1])).toContain('/users/' + users[1].id + '/picture');
|
||||
done();
|
||||
});
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: {data: fakeInvolveUserList}
|
||||
});
|
||||
});
|
||||
|
||||
it('should return user image url', () => {
|
||||
let url = service.getUserImage(firstInvolvedUser);
|
||||
|
||||
expect(url).toContain('/users/' + firstInvolvedUser.id + '/picture');
|
||||
});
|
||||
|
||||
it('should return empty list when there are no users to involve', (done) => {
|
||||
service.getWorkflowUsers('fake-task-id', 'fake-filter').subscribe(
|
||||
(users: UserProcessModel[]) => {
|
||||
expect(users).toBeDefined();
|
||||
expect(users.length).toBe(0);
|
||||
done();
|
||||
});
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: {}
|
||||
});
|
||||
});
|
||||
|
||||
it('getWorkflowUsers catch errors call', (done) => {
|
||||
service.getWorkflowUsers('fake-task-id', 'fake-filter').subscribe(() => {
|
||||
}, () => {
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 403
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to involve people in the task', (done) => {
|
||||
service.involveUserWithTask('fake-task-id', 'fake-user-id').subscribe(
|
||||
() => {
|
||||
expect(jasmine.Ajax.requests.mostRecent().method).toBe('PUT');
|
||||
expect(jasmine.Ajax.requests.mostRecent().url).toContain('tasks/fake-task-id/action/involve');
|
||||
done();
|
||||
});
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200
|
||||
});
|
||||
});
|
||||
|
||||
it('involveUserWithTask catch errors call', (done) => {
|
||||
service.involveUserWithTask('fake-task-id', 'fake-user-id').subscribe(() => {
|
||||
}, () => {
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 403
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to remove involved people from task', (done) => {
|
||||
service.removeInvolvedUser('fake-task-id', 'fake-user-id').subscribe(
|
||||
() => {
|
||||
expect(jasmine.Ajax.requests.mostRecent().method).toBe('PUT');
|
||||
expect(jasmine.Ajax.requests.mostRecent().url).toContain('tasks/fake-task-id/action/remove-involved');
|
||||
done();
|
||||
});
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200
|
||||
});
|
||||
});
|
||||
|
||||
it('removeInvolvedUser catch errors call', (done) => {
|
||||
service.removeInvolvedUser('fake-task-id', 'fake-user-id').subscribe(() => {
|
||||
}, () => {
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 403
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
80
lib/core/services/people-process.service.ts
Normal file
80
lib/core/services/people-process.service.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { Response } from '@angular/http';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { UserProcessModel } from '../models/user-process.model';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { LogService } from './log.service';
|
||||
|
||||
@Injectable()
|
||||
export class PeopleProcessService {
|
||||
|
||||
constructor(private alfrescoJsApi: AlfrescoApiService,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
getWorkflowUsers(taskId?: string, searchWord?: string): Observable<UserProcessModel[]> {
|
||||
let option = { excludeTaskId: taskId, filter: searchWord };
|
||||
return Observable.fromPromise(this.getWorkflowUserApi(option))
|
||||
.map((response: any) => <UserProcessModel[]> response.data || [])
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
getUserImage(user: UserProcessModel): string {
|
||||
return this.getUserProfileImageApi(user.id);
|
||||
}
|
||||
|
||||
involveUserWithTask(taskId: string, idToInvolve: string): Observable<UserProcessModel[]> {
|
||||
let node = {userId: idToInvolve};
|
||||
return Observable.fromPromise(this.involveUserToTaskApi(taskId, node))
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
removeInvolvedUser(taskId: string, idToRemove: string): Observable<UserProcessModel[]> {
|
||||
let node = {userId: idToRemove};
|
||||
return Observable.fromPromise(this.removeInvolvedUserFromTaskApi(taskId, node))
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
private getWorkflowUserApi(options: any) {
|
||||
return this.alfrescoJsApi.getInstance().activiti.usersWorkflowApi.getUsers(options);
|
||||
}
|
||||
|
||||
private involveUserToTaskApi(taskId: string, node: any) {
|
||||
return this.alfrescoJsApi.getInstance().activiti.taskActionsApi.involveUser(taskId, node);
|
||||
}
|
||||
|
||||
private removeInvolvedUserFromTaskApi(taskId: string, node: any) {
|
||||
return this.alfrescoJsApi.getInstance().activiti.taskActionsApi.removeInvolvedUser(taskId, node);
|
||||
}
|
||||
|
||||
private getUserProfileImageApi(userId: number) {
|
||||
return this.alfrescoJsApi.getInstance().activiti.userApi.getUserProfilePictureUrl(userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw the error
|
||||
* @param error
|
||||
* @returns {ErrorObservable}
|
||||
*/
|
||||
private handleError(error: Response) {
|
||||
this.logService.error(error);
|
||||
return Observable.throw(error || 'Server error');
|
||||
}
|
||||
}
|
53
lib/core/services/public-api.ts
Normal file
53
lib/core/services/public-api.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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.
|
||||
*/
|
||||
|
||||
export * from './authentication.service';
|
||||
export * from './alfresco-api.service';
|
||||
export * from './settings.service';
|
||||
export * from './content.service';
|
||||
export * from './auth-guard.service';
|
||||
export * from './auth-guard-ecm.service';
|
||||
export * from './auth-guard-bpm.service';
|
||||
export * from './apps-process.service';
|
||||
export * from './page-title.service';
|
||||
export * from './storage.service';
|
||||
export * from './cookie.service';
|
||||
export * from './renditions.service';
|
||||
export * from './notification.service';
|
||||
export * from './log.service';
|
||||
export * from './translation.service';
|
||||
export * from './translate-loader.service';
|
||||
export * from './thumbnail.service';
|
||||
export * from './upload.service';
|
||||
export * from './dynamic-component-mapper.service';
|
||||
export * from './card-item-types.service';
|
||||
export * from './card-view-update.service';
|
||||
export * from './user-preferences.service';
|
||||
export * from './highlight-transform.service';
|
||||
export * from './deleted-nodes-api.service';
|
||||
export * from './favorites-api.service';
|
||||
export * from './nodes-api.service';
|
||||
export * from './people-content.service';
|
||||
export * from './people-process.service';
|
||||
export * from './search-api.service';
|
||||
export * from './search.service';
|
||||
export * from './shared-links-api.service';
|
||||
export * from './sites-api.service';
|
||||
export * from './discovery-api.service';
|
||||
export * from './comment-process.service';
|
||||
|
||||
export * from './service.module';
|
172
lib/core/services/renditions.service.spec.ts
Normal file
172
lib/core/services/renditions.service.spec.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, TestBed } from '@angular/core/testing';
|
||||
import { fakeRedition, fakeReditionCreated, fakeReditionsList } from '../mock/renditionsService.mock';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { AppConfigModule } from '../app-config';
|
||||
import { LogService } from './log.service';
|
||||
import { RenditionsService } from './renditions.service';
|
||||
import { StorageService } from './storage.service';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
describe('RenditionsService', () => {
|
||||
let service: RenditionsService;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppConfigModule
|
||||
],
|
||||
declarations: [
|
||||
],
|
||||
providers: [
|
||||
AlfrescoApiService,
|
||||
RenditionsService,
|
||||
SettingsService,
|
||||
StorageService,
|
||||
LogService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
jasmine.Ajax.install();
|
||||
service = TestBed.get(RenditionsService);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
it('Get redition list service should return the list', (done) => {
|
||||
service.getRenditionsListByNodeId('fake-node-id').subscribe((res) => {
|
||||
expect(res.list.entries[0].entry.id).toBe('avatar');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(fakeReditionsList)
|
||||
});
|
||||
});
|
||||
|
||||
it('Create redition service should call the server with the ID passed and the asked encoding', (done) => {
|
||||
service.createRendition('fake-node-id', 'pdf').subscribe((res) => {
|
||||
expect(jasmine.Ajax.requests.mostRecent().method).toBe('POST');
|
||||
expect(jasmine.Ajax.requests.mostRecent().url).toContain('/ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/fake-node-id/renditions');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: ''
|
||||
});
|
||||
});
|
||||
|
||||
describe('convert', () => {
|
||||
|
||||
it('should call the server with the ID passed and the asked encoding for creation', (done) => {
|
||||
service.convert('fake-node-id', 'pdf', 1000);
|
||||
|
||||
expect(jasmine.Ajax.requests.mostRecent().method).toBe('POST');
|
||||
expect(jasmine.Ajax.requests.mostRecent().url).toContain('/ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/fake-node-id/renditions');
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Get redition service should catch the error', (done) => {
|
||||
service.getRenditionsListByNodeId('fake-node-id').subscribe((res) => {
|
||||
}, (res) => {
|
||||
done();
|
||||
}
|
||||
);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 403,
|
||||
contentType: 'application/json',
|
||||
responseText: 'error'
|
||||
});
|
||||
});
|
||||
|
||||
it('isConversionPossible should return true if is possible convert', (done) => {
|
||||
service.isConversionPossible('fake-node-id', 'pdf').subscribe((res) => {
|
||||
expect(res).toBe(true);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(fakeRedition)
|
||||
});
|
||||
});
|
||||
|
||||
it('isConversionPossible should return false if is not possible to convert', (done) => {
|
||||
service.isConversionPossible('fake-node-id', 'pdf').subscribe((res) => {
|
||||
expect(res).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 403,
|
||||
contentType: 'application/json'
|
||||
});
|
||||
});
|
||||
|
||||
it('isRenditionsAvailable should return true if the conversion exist', (done) => {
|
||||
service.isRenditionAvailable('fake-node-id', 'pdf').subscribe((res) => {
|
||||
expect(res).toBe(true);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(fakeReditionCreated)
|
||||
});
|
||||
});
|
||||
|
||||
it('isRenditionsAvailable should return false if the conversion not exist', (done) => {
|
||||
service.isRenditionAvailable('fake-node-id', 'pdf').subscribe((res) => {
|
||||
expect(res).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify(fakeRedition)
|
||||
});
|
||||
});
|
||||
|
||||
it('isRenditionsAvailable should return false if the conversion get error', (done) => {
|
||||
service.isRenditionAvailable('fake-node-id', 'pdf').subscribe((res) => {
|
||||
expect(res).toBe(false);
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 400,
|
||||
contentType: 'application/json'
|
||||
});
|
||||
});
|
||||
});
|
96
lib/core/services/renditions.service.ts
Normal file
96
lib/core/services/renditions.service.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { RenditionEntry, RenditionPaging } from 'alfresco-js-api';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
|
||||
/**
|
||||
* RenditionsService
|
||||
*
|
||||
* @returns {RenditionsService} .
|
||||
*/
|
||||
@Injectable()
|
||||
export class RenditionsService {
|
||||
|
||||
constructor(private apiService: AlfrescoApiService) {
|
||||
}
|
||||
|
||||
isRenditionAvailable(nodeId: string, encoding: string): Observable<boolean> {
|
||||
return Observable.create((observer) => {
|
||||
this.getRendition(nodeId, encoding).subscribe(
|
||||
(res) => {
|
||||
let isAvailable = true;
|
||||
if (res.entry.status.toString() === 'NOT_CREATED') {
|
||||
isAvailable = false;
|
||||
}
|
||||
observer.next(isAvailable);
|
||||
observer.complete();
|
||||
},
|
||||
() => {
|
||||
observer.next(false);
|
||||
observer.complete();
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
isConversionPossible(nodeId: string, encoding: string): Observable<boolean> {
|
||||
return Observable.create((observer) => {
|
||||
this.getRendition(nodeId, encoding).subscribe(
|
||||
() => {
|
||||
observer.next(true);
|
||||
observer.complete();
|
||||
},
|
||||
() => {
|
||||
observer.next(false);
|
||||
observer.complete();
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
getRenditionUrl(nodeId: string, encoding: string): string {
|
||||
return this.apiService.contentApi.getRenditionUrl(nodeId, 'pdf');
|
||||
}
|
||||
|
||||
getRendition(nodeId: string, encoding: string): Observable<RenditionEntry> {
|
||||
return Observable.fromPromise(this.apiService.renditionsApi.getRendition(nodeId, encoding));
|
||||
}
|
||||
|
||||
getRenditionsListByNodeId(nodeId: string): Observable<RenditionPaging> {
|
||||
return Observable.fromPromise(this.apiService.renditionsApi.getRenditions(nodeId));
|
||||
}
|
||||
|
||||
createRendition(nodeId: string, encoding: string): Observable<{}> {
|
||||
return Observable.fromPromise(this.apiService.renditionsApi.createRendition(nodeId, {id: encoding}));
|
||||
}
|
||||
|
||||
convert(nodeId: string, encoding: string, pollingInterval: number = 1000) {
|
||||
return this.createRendition(nodeId, encoding)
|
||||
.concatMap(() => this.pollRendition(nodeId, encoding, pollingInterval));
|
||||
}
|
||||
|
||||
private pollRendition(nodeId: string, encoding: string, interval: number = 1000) {
|
||||
return Observable.interval(interval)
|
||||
.switchMap(() => this.getRendition(nodeId, encoding))
|
||||
.takeWhile((data) => {
|
||||
return (data.entry.status.toString() !== 'CREATED');
|
||||
});
|
||||
}
|
||||
}
|
46
lib/core/services/search-api.service.ts
Normal file
46
lib/core/services/search-api.service.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
import { NodePaging } from 'alfresco-js-api';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
|
||||
@Injectable()
|
||||
export class SearchApiService {
|
||||
|
||||
constructor(private apiService: AlfrescoApiService) {}
|
||||
|
||||
private get searchApi() {
|
||||
return this.apiService.getInstance().search.searchApi;
|
||||
}
|
||||
|
||||
search(query: any): Observable<NodePaging> {
|
||||
const { searchApi, handleError } = this;
|
||||
const searchQuery = Object.assign(query);
|
||||
const promise = searchApi.search(searchQuery);
|
||||
|
||||
return Observable
|
||||
.fromPromise(promise)
|
||||
.catch(handleError);
|
||||
}
|
||||
|
||||
private handleError(error): Observable<any> {
|
||||
return Observable.of(error);
|
||||
}
|
||||
}
|
129
lib/core/services/search.service.spec.ts
Normal file
129
lib/core/services/search.service.spec.ts
Normal file
@@ -0,0 +1,129 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, TestBed } from '@angular/core/testing';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { fakeApi, fakeError, fakeSearch } from '../mock/search.service.mock';
|
||||
import { CookieServiceMock } from './../mock/cookie.service.mock';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { AppConfigModule } from '../app-config';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { CookieService } from './cookie.service';
|
||||
import { LogService } from './log.service';
|
||||
import { SearchService } from './search.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
describe('SearchService', () => {
|
||||
|
||||
let service: SearchService;
|
||||
let apiService: AlfrescoApiService;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppConfigModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
SearchService,
|
||||
AuthenticationService,
|
||||
AlfrescoApiService,
|
||||
SettingsService,
|
||||
AuthenticationService,
|
||||
StorageService,
|
||||
UserPreferencesService,
|
||||
{ provide: CookieService, useClass: CookieServiceMock },
|
||||
LogService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.get(SearchService);
|
||||
apiService = TestBed.get(AlfrescoApiService);
|
||||
spyOn(apiService, 'getInstance').and.returnValue(fakeApi);
|
||||
});
|
||||
|
||||
it('should call search API with no additional options', (done) => {
|
||||
let searchTerm = 'searchTerm63688';
|
||||
spyOn(fakeApi.core.queriesApi, 'findNodes').and.returnValue(Promise.resolve(fakeSearch));
|
||||
service.getNodeQueryResults(searchTerm).subscribe(
|
||||
() => {
|
||||
expect(fakeApi.core.queriesApi.findNodes).toHaveBeenCalledWith(searchTerm, undefined);
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should call search API with additional options', (done) => {
|
||||
let searchTerm = 'searchTerm63688', options = {
|
||||
include: [ 'path' ],
|
||||
rootNodeId: '-root-',
|
||||
nodeType: 'cm:content'
|
||||
};
|
||||
spyOn(fakeApi.core.queriesApi, 'findNodes').and.returnValue(Promise.resolve(fakeSearch));
|
||||
service.getNodeQueryResults(searchTerm, options).subscribe(
|
||||
() => {
|
||||
expect(fakeApi.core.queriesApi.findNodes).toHaveBeenCalledWith(searchTerm, options);
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should return search results returned from the API', (done) => {
|
||||
service.getNodeQueryResults('').subscribe(
|
||||
(res: any) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res).toEqual(fakeSearch);
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should notify errors returned from the API', (done) => {
|
||||
spyOn(fakeApi.core.queriesApi, 'findNodes').and.returnValue(Promise.reject(fakeError));
|
||||
service.getNodeQueryResults('').subscribe(
|
||||
() => {},
|
||||
(res: any) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res).toEqual(fakeError);
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should notify a general error if the API does not return a specific error', (done) => {
|
||||
spyOn(fakeApi.core.queriesApi, 'findNodes').and.returnValue(Promise.reject(null));
|
||||
service.getNodeQueryResults('').subscribe(
|
||||
() => {},
|
||||
(res: any) => {
|
||||
expect(res).toBeDefined();
|
||||
expect(res).toEqual('Server error');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
});
|
64
lib/core/services/search.service.ts
Normal file
64
lib/core/services/search.service.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { NodePaging } from 'alfresco-js-api';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
|
||||
/**
|
||||
* Internal service used by Document List component.
|
||||
*/
|
||||
@Injectable()
|
||||
export class SearchService {
|
||||
|
||||
constructor(public authService: AuthenticationService,
|
||||
private apiService: AlfrescoApiService) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a search against the repository
|
||||
*
|
||||
* @param term Search term
|
||||
* @param options Additional options passed to the search
|
||||
* @returns {Observable<NodePaging>} Search results
|
||||
*/
|
||||
getNodeQueryResults(term: string, options?: SearchOptions): Observable<NodePaging> {
|
||||
return Observable.fromPromise(this.getQueryNodesPromise(term, options))
|
||||
.map(res => <NodePaging> res)
|
||||
.catch(err => this.handleError(err));
|
||||
}
|
||||
|
||||
getQueryNodesPromise(term: string, opts: SearchOptions): Promise<NodePaging> {
|
||||
return this.apiService.getInstance().core.queriesApi.findNodes(term, opts);
|
||||
}
|
||||
|
||||
private handleError(error: any): Observable<any> {
|
||||
return Observable.throw(error || 'Server error');
|
||||
}
|
||||
}
|
||||
|
||||
export interface SearchOptions {
|
||||
skipCount?: number;
|
||||
maxItems?: number;
|
||||
rootNodeId?: string;
|
||||
nodeType?: string;
|
||||
include?: string[];
|
||||
orderBy?: string;
|
||||
fields?: string[];
|
||||
}
|
96
lib/core/services/service.module.ts
Normal file
96
lib/core/services/service.module.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { NgModule } from '@angular/core';
|
||||
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { AppsProcessService } from './apps-process.service';
|
||||
import { AuthGuardBpm } from './auth-guard-bpm.service';
|
||||
import { AuthGuardEcm } from './auth-guard-ecm.service';
|
||||
import { AuthGuard } from './auth-guard.service';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { CardItemTypeService } from './card-item-types.service';
|
||||
import { CardViewUpdateService } from './card-view-update.service';
|
||||
import { CommentProcessService } from './comment-process.service';
|
||||
import { ContentService } from './content.service';
|
||||
import { CookieService } from './cookie.service';
|
||||
import { DeletedNodesApiService } from './deleted-nodes-api.service';
|
||||
import { DiscoveryApiService } from './discovery-api.service';
|
||||
import { FavoritesApiService } from './favorites-api.service';
|
||||
import { HighlightTransformService } from './highlight-transform.service';
|
||||
import { LogService } from './log.service';
|
||||
import { NodesApiService } from './nodes-api.service';
|
||||
import { NotificationService } from './notification.service';
|
||||
import { PageTitleService } from './page-title.service';
|
||||
import { PeopleContentService } from './people-content.service';
|
||||
import { PeopleProcessService } from './people-process.service';
|
||||
import { RenditionsService } from './renditions.service';
|
||||
import { SearchApiService } from './search-api.service';
|
||||
import { SearchService } from './search.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { SharedLinksApiService } from './shared-links-api.service';
|
||||
import { SitesApiService } from './sites-api.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { ThumbnailService } from './thumbnail.service';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { TranslationService } from './translation.service';
|
||||
import { UploadService } from './upload.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [],
|
||||
declarations: [],
|
||||
providers: [
|
||||
AuthenticationService,
|
||||
AlfrescoApiService,
|
||||
SettingsService,
|
||||
ContentService,
|
||||
AuthGuard,
|
||||
AuthGuardEcm,
|
||||
AuthGuardBpm,
|
||||
AppsProcessService,
|
||||
PageTitleService,
|
||||
StorageService,
|
||||
CookieService,
|
||||
RenditionsService,
|
||||
NotificationService,
|
||||
LogService,
|
||||
TranslationService,
|
||||
TranslateLoaderService,
|
||||
ThumbnailService,
|
||||
UploadService,
|
||||
CardItemTypeService,
|
||||
CardViewUpdateService,
|
||||
UserPreferencesService,
|
||||
HighlightTransformService,
|
||||
DeletedNodesApiService,
|
||||
FavoritesApiService,
|
||||
NodesApiService,
|
||||
PeopleContentService,
|
||||
PeopleProcessService,
|
||||
SearchApiService,
|
||||
SearchService,
|
||||
SharedLinksApiService,
|
||||
SitesApiService,
|
||||
DiscoveryApiService,
|
||||
CommentProcessService
|
||||
],
|
||||
exports: [
|
||||
]
|
||||
})
|
||||
export class ServiceModule {
|
||||
}
|
60
lib/core/services/settings.service.spec.ts
Normal file
60
lib/core/services/settings.service.spec.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, TestBed } from '@angular/core/testing';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { AppConfigModule } from '../app-config';
|
||||
import { LogService } from './log.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
describe('SettingsService', () => {
|
||||
|
||||
let service: SettingsService;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppConfigModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
AlfrescoApiService,
|
||||
SettingsService,
|
||||
UserPreferencesService,
|
||||
StorageService,
|
||||
LogService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.get(SettingsService);
|
||||
});
|
||||
|
||||
it('should be exposed by the module', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
});
|
77
lib/core/services/settings.service.ts
Normal file
77
lib/core/services/settings.service.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { LogService } from './log.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
@Injectable()
|
||||
export class SettingsService {
|
||||
|
||||
constructor(
|
||||
private appConfig: AppConfigService,
|
||||
private logService: LogService,
|
||||
private preferences: UserPreferencesService) {
|
||||
}
|
||||
|
||||
/** @deprecated in 1.6.0 */
|
||||
public get ecmHost(): string {
|
||||
this.logService.log('SettingsService.ecmHost is deprecated. Use AppConfigService instead.');
|
||||
return this.appConfig.get<string>('ecmHost');
|
||||
}
|
||||
|
||||
/** @deprecated in 1.7.0 */
|
||||
public set csrfDisabled(csrfDisabled: boolean) {
|
||||
this.logService.log(`SettingsService.csrfDisabled is deprecated. Use UserPreferencesService.disableCSRF instead.`);
|
||||
this.preferences.disableCSRF = csrfDisabled;
|
||||
}
|
||||
|
||||
/** @deprecated in 1.6.0 */
|
||||
public set ecmHost(ecmHostUrl: string) {
|
||||
this.logService.log('SettingsService.ecmHost is deprecated. Use AppConfigService instead.');
|
||||
}
|
||||
|
||||
/** @deprecated in 1.6.0 */
|
||||
public get bpmHost(): string {
|
||||
this.logService.log('SettingsService.bpmHost is deprecated. Use AppConfigService instead.');
|
||||
return this.appConfig.get<string>('bpmHost');
|
||||
}
|
||||
|
||||
/** @deprecated in 1.6.0 */
|
||||
public set bpmHost(bpmHostUrl: string) {
|
||||
this.logService.log('SettingsService.bpmHost is deprecated. Use AppConfigService instead.');
|
||||
}
|
||||
|
||||
/** @deprecated in 1.6.0 */
|
||||
public getBPMApiBaseUrl(): string {
|
||||
this.logService.log('SettingsService.getBPMApiBaseUrl is deprecated.');
|
||||
return this.bpmHost + '/activiti-app';
|
||||
}
|
||||
|
||||
/** @deprecated in 1.7.0 */
|
||||
public getProviders(): string {
|
||||
this.logService.log(`SettingsService.getProviders is deprecated. Use UserPreferencesService.authType instead.`);
|
||||
return this.preferences.authType;
|
||||
}
|
||||
|
||||
/** @deprecated in 1.7.0 */
|
||||
public setProviders(providers: string) {
|
||||
this.logService.log(`SettingsService.getProviders is deprecated. Use UserPreferencesService.authType instead.`);
|
||||
this.preferences.authType = providers;
|
||||
}
|
||||
}
|
54
lib/core/services/shared-links-api.service.ts
Normal file
54
lib/core/services/shared-links-api.service.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { NodePaging } from 'alfresco-js-api';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
@Injectable()
|
||||
export class SharedLinksApiService {
|
||||
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService,
|
||||
private preferences: UserPreferencesService) {}
|
||||
|
||||
private get sharedLinksApi() {
|
||||
return this.apiService.getInstance().core.sharedlinksApi;
|
||||
}
|
||||
|
||||
getSharedLinks(options: any = {}): Observable<NodePaging> {
|
||||
const { sharedLinksApi, handleError } = this;
|
||||
const defaultOptions = {
|
||||
maxItems: this.preferences.paginationSize,
|
||||
skipCount: 0,
|
||||
include: [ 'properties', 'allowableOperations' ]
|
||||
};
|
||||
const queryOptions = Object.assign({}, defaultOptions, options);
|
||||
const promise = sharedLinksApi
|
||||
.findSharedLinks(queryOptions);
|
||||
|
||||
return Observable
|
||||
.fromPromise(promise)
|
||||
.catch(handleError);
|
||||
}
|
||||
|
||||
private handleError(error: any): Observable<any> {
|
||||
return Observable.of(error);
|
||||
}
|
||||
}
|
168
lib/core/services/sites-api.service.spec.ts
Normal file
168
lib/core/services/sites-api.service.spec.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, TestBed } from '@angular/core/testing';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { AppConfigModule, AppConfigService } from '../app-config';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { LogService } from './log.service';
|
||||
import { SitesApiService } from './sites-api.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
describe('Sites service', () => {
|
||||
|
||||
let service;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppConfigModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
SitesApiService,
|
||||
AlfrescoApiService,
|
||||
UserPreferencesService,
|
||||
AuthenticationService,
|
||||
SettingsService,
|
||||
StorageService,
|
||||
LogService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
let appConfig: AppConfigService = TestBed.get(AppConfigService);
|
||||
appConfig.config = {
|
||||
ecmHost: 'http://localhost:9876/ecm',
|
||||
files: {
|
||||
excluded: ['.DS_Store', 'desktop.ini', '.git', '*.git']
|
||||
}
|
||||
};
|
||||
|
||||
service = TestBed.get(SitesApiService);
|
||||
jasmine.Ajax.install();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
it('Should get a list of users sites', (done) => {
|
||||
service.getSites().subscribe((data) => {
|
||||
expect(data[0].title).toBe('FAKE');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: {
|
||||
'list': {
|
||||
'pagination': {
|
||||
'count': 1,
|
||||
'hasMoreItems': false,
|
||||
'totalItems': 1,
|
||||
'skipCount': 0,
|
||||
'maxItems': 100
|
||||
},
|
||||
'entries': [
|
||||
{
|
||||
'entry': {
|
||||
'role': 'SiteManager',
|
||||
'visibility': 'PUBLIC',
|
||||
'guid': 'b4cff62a-664d-4d45-9302-98723eac1319',
|
||||
'description': 'This is a Sample Alfresco Team site.',
|
||||
'id': 'swsdp',
|
||||
'title': 'FAKE'
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('Should get single sites via siteId', (done) => {
|
||||
service.getSite('fake-site-id').subscribe((data) => {
|
||||
expect(data.title).toBe('FAKE-SINGLE-TITLE');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 200,
|
||||
contentType: 'json',
|
||||
responseText: {
|
||||
'entry': {
|
||||
'role': 'SiteManager',
|
||||
'visibility': 'PUBLIC',
|
||||
'guid': 'b4cff62a-664d-4d45-9302-98723eac1319',
|
||||
'description': 'This is a Sample Alfresco Team site.',
|
||||
'id': 'swsdp',
|
||||
'preset': 'site-dashboard',
|
||||
'title': 'FAKE-SINGLE-TITLE'
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('deleteSite should perform a call against the server', (done) => {
|
||||
service.deleteSite('fake-site-id').subscribe(() => {
|
||||
expect(jasmine.Ajax.requests.mostRecent().method).toBe('DELETE');
|
||||
expect(jasmine.Ajax.requests.mostRecent().url)
|
||||
.toContain('alfresco/api/-default-/public/alfresco/versions/1/sites/fake-site-id');
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 204
|
||||
});
|
||||
});
|
||||
|
||||
it('getSites catch errors call', (done) => {
|
||||
service.getSites().subscribe(() => {
|
||||
}, () => {
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 403
|
||||
});
|
||||
});
|
||||
|
||||
it('getSite catch errors call', (done) => {
|
||||
service.getSite('error-id').subscribe(() => {
|
||||
}, () => {
|
||||
done();
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
status: 403
|
||||
});
|
||||
});
|
||||
});
|
80
lib/core/services/sites-api.service.ts
Normal file
80
lib/core/services/sites-api.service.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { Response } from '@angular/http';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { SiteModel } from '../models/site.model';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
|
||||
@Injectable()
|
||||
export class SitesApiService {
|
||||
|
||||
constructor(
|
||||
private apiService: AlfrescoApiService) { }
|
||||
|
||||
getSites(opts: any = {}): any {
|
||||
const defaultOptions = {
|
||||
skipCount: 0,
|
||||
include: ['properties']
|
||||
};
|
||||
const queryOptions = Object.assign({}, defaultOptions, opts);
|
||||
return Observable.fromPromise(this.apiService.getInstance().core.sitesApi.getSites(queryOptions))
|
||||
.map((res) => this.convertToModel(res))
|
||||
.catch(this.handleError);
|
||||
}
|
||||
|
||||
getSite(siteId: string, opts?: any): any {
|
||||
return Observable.fromPromise(this.apiService.getInstance().core.sitesApi.getSite(siteId, opts))
|
||||
.map((res: any) => new SiteModel(res))
|
||||
.catch(this.handleError);
|
||||
}
|
||||
|
||||
deleteSite(siteId: string, permanentFlag: boolean = true): any {
|
||||
let options: any = {};
|
||||
options.permanent = permanentFlag;
|
||||
return Observable.fromPromise(this.apiService.getInstance().core.sitesApi.deleteSite(siteId, options)
|
||||
.catch(this.handleError));
|
||||
}
|
||||
|
||||
getSiteContent(siteId: string): Observable<any> {
|
||||
return this.getSite(siteId, { relations: ['containers'] });
|
||||
}
|
||||
|
||||
getSiteMembers(siteId: string): Observable<any> {
|
||||
return this.getSite(siteId, { relations: ['members'] });
|
||||
}
|
||||
|
||||
private handleError(error: Response): any {
|
||||
console.error(error);
|
||||
return Observable.throw(error || 'Server error');
|
||||
}
|
||||
|
||||
private convertToModel(response: any) {
|
||||
let convertedList: SiteModel[] = [];
|
||||
if (response &&
|
||||
response.list &&
|
||||
response.list.entries &&
|
||||
response.list.entries.length > 0) {
|
||||
response.list.entries.forEach((element: any) => {
|
||||
element.pagination = response.list.pagination;
|
||||
convertedList.push(new SiteModel(element));
|
||||
});
|
||||
}
|
||||
return convertedList;
|
||||
}
|
||||
}
|
82
lib/core/services/storage.service.ts
Normal file
82
lib/core/services/storage.service.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class StorageService {
|
||||
|
||||
private memoryStore: { [key: string]: any } = {};
|
||||
private useLocalStorage: boolean = false;
|
||||
|
||||
constructor() {
|
||||
this.useLocalStorage = this.storageAvailable('localStorage');
|
||||
}
|
||||
|
||||
getItem(key: string): string | null {
|
||||
if (this.useLocalStorage) {
|
||||
return localStorage.getItem(key);
|
||||
} else {
|
||||
return this.memoryStore.hasOwnProperty(key) ? this.memoryStore[key] : null;
|
||||
}
|
||||
}
|
||||
|
||||
setItem(key: string, data: string) {
|
||||
if (this.useLocalStorage) {
|
||||
localStorage.setItem(key, data);
|
||||
} else {
|
||||
this.memoryStore[key] = data.toString();
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
if (this.useLocalStorage) {
|
||||
localStorage.clear();
|
||||
} else {
|
||||
this.memoryStore = {};
|
||||
}
|
||||
}
|
||||
|
||||
removeItem(key: string) {
|
||||
if (this.useLocalStorage) {
|
||||
localStorage.removeItem(key);
|
||||
} else {
|
||||
delete this.memoryStore[key];
|
||||
}
|
||||
}
|
||||
|
||||
hasItem(key: string): boolean {
|
||||
if (this.useLocalStorage) {
|
||||
return localStorage.getItem(key) ? true : false;
|
||||
} else {
|
||||
return this.memoryStore.hasOwnProperty(key);
|
||||
}
|
||||
}
|
||||
|
||||
private storageAvailable(type: string): boolean {
|
||||
try {
|
||||
let storage = window[type];
|
||||
const key = '__storage_test__';
|
||||
storage.setItem(key, key);
|
||||
storage.removeItem(key, key);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
95
lib/core/services/thumbnail.service.spec.ts
Normal file
95
lib/core/services/thumbnail.service.spec.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { HttpClientModule } from '@angular/common/http';
|
||||
import { async, TestBed } from '@angular/core/testing';
|
||||
import { MatIconRegistry } from '@angular/material';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { CookieServiceMock } from './../mock/cookie.service.mock';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { ContentService } from './content.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { CookieService } from './cookie.service';
|
||||
import { LogService } from './log.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { ThumbnailService } from './thumbnail.service';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
describe('ThumbnailService', () => {
|
||||
|
||||
let service: ThumbnailService;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
HttpClientModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
UserPreferencesService,
|
||||
AuthenticationService,
|
||||
ContentService,
|
||||
SettingsService,
|
||||
AppConfigService,
|
||||
{ provide: CookieService, useClass: CookieServiceMock },
|
||||
ThumbnailService,
|
||||
AlfrescoApiService,
|
||||
SettingsService,
|
||||
StorageService,
|
||||
LogService,
|
||||
MatIconRegistry
|
||||
]
|
||||
}).compileComponents();
|
||||
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
service = TestBed.get(ThumbnailService);
|
||||
});
|
||||
|
||||
it('should return the correct icon for a plain text file', () => {
|
||||
expect(service.getMimeTypeIcon('text/plain')).toContain('ft_ic_document');
|
||||
});
|
||||
|
||||
it('should return the correct icon for a PNG file', () => {
|
||||
expect(service.getMimeTypeIcon('image/png')).toContain('ft_ic_raster_image');
|
||||
});
|
||||
|
||||
it('should return the correct icon for a MP4 video file', () => {
|
||||
expect(service.getMimeTypeIcon('video/mp4')).toContain('ft_ic_video');
|
||||
});
|
||||
|
||||
it('should return a generic icon for an unknown file', () => {
|
||||
expect(service.getMimeTypeIcon('x-unknown/yyy')).toContain('ft_ic_miscellaneous');
|
||||
});
|
||||
|
||||
it('should return the thumbnail URL for a content item', () => {
|
||||
spyOn(service.contentService, 'getDocumentThumbnailUrl').and.returnValue('/fake-thumbnail.png');
|
||||
expect(service.getDocumentThumbnailUrl({})).toContain('/fake-thumbnail.png');
|
||||
});
|
||||
|
||||
});
|
152
lib/core/services/thumbnail.service.ts
Normal file
152
lib/core/services/thumbnail.service.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { MatIconRegistry } from '@angular/material';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { ContentService } from './content.service';
|
||||
|
||||
declare var require: any;
|
||||
|
||||
@Injectable()
|
||||
export class ThumbnailService {
|
||||
|
||||
DEFAULT_ICON: string = require('../assets/images/ft_ic_miscellaneous.svg');
|
||||
|
||||
mimeTypeIcons: any = {
|
||||
'image/png': require('../assets/images/ft_ic_raster_image.svg'),
|
||||
'image/jpeg': require('../assets/images/ft_ic_raster_image.svg'),
|
||||
'image/gif': require('../assets/images/ft_ic_raster_image.svg'),
|
||||
'application/pdf': require('../assets/images/ft_ic_pdf.svg'),
|
||||
'application/vnd.ms-excel': require('../assets/images/ft_ic_ms_excel.svg'),
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': require('../assets/images/ft_ic_ms_excel.svg'),
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.template': require('../assets/images/ft_ic_ms_excel.svg'),
|
||||
'application/msword': require('../assets/images/ft_ic_ms_word.svg'),
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': require('../assets/images/ft_ic_ms_word.svg'),
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.template': require('../assets/images/ft_ic_ms_word.svg'),
|
||||
'application/vnd.ms-powerpoint': require('../assets/images/ft_ic_ms_powerpoint.svg'),
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation': require('../assets/images/ft_ic_ms_powerpoint.svg'),
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.template': require('../assets/images/ft_ic_ms_powerpoint.svg'),
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.slideshow': require('../assets/images/ft_ic_ms_powerpoint.svg'),
|
||||
'video/mp4': require('../assets/images/ft_ic_video.svg'),
|
||||
'text/plain': require('../assets/images/ft_ic_document.svg'),
|
||||
'application/x-javascript': require('../assets/images/ft_ic_document.svg'),
|
||||
'application/json': require('../assets/images/ft_ic_document.svg'),
|
||||
'image/svg+xml': require('../assets/images/ft_ic_vector_image.svg'),
|
||||
'text/html': require('../assets/images/ft_ic_website.svg'),
|
||||
'application/x-compressed': require('../assets/images/ft_ic_archive.svg'),
|
||||
'application/x-zip-compressed': require('../assets/images/ft_ic_archive.svg'),
|
||||
'application/zip': require('../assets/images/ft_ic_archive.svg'),
|
||||
'application/vnd.apple.keynote': require('../assets/images/ft_ic_presentation.svg'),
|
||||
'application/vnd.apple.pages': require('../assets/images/ft_ic_document.svg'),
|
||||
'application/vnd.apple.numbers': require('../assets/images/ft_ic_spreadsheet.svg'),
|
||||
'folder': require('../assets/images/ft_ic_folder.svg'),
|
||||
'disable/folder': require('../assets/images/ft_ic_folder_disable.svg'),
|
||||
'selected': require('../assets/images/ft_ic_selected.svg')
|
||||
};
|
||||
|
||||
constructor(public contentService: ContentService, matIconRegistry: MatIconRegistry, sanitizer: DomSanitizer) {
|
||||
matIconRegistry.addSvgIcon('image/png',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_raster_image.svg')));
|
||||
matIconRegistry.addSvgIcon('image/jpeg',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_raster_image.svg')));
|
||||
matIconRegistry.addSvgIcon('image/gif',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_raster_image.svg')));
|
||||
matIconRegistry.addSvgIcon('application/pdf',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_pdf.svg')));
|
||||
matIconRegistry.addSvgIcon('application/vnd.ms-excel',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_ms_excel.svg')));
|
||||
matIconRegistry.addSvgIcon('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_ms_excel.svg')));
|
||||
matIconRegistry.addSvgIcon('application/vnd.openxmlformats-officedocument.spreadsheetml.template',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_ms_excel.svg')));
|
||||
matIconRegistry.addSvgIcon('application/msword',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_ms_word.svg')));
|
||||
matIconRegistry.addSvgIcon('application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_ms_word.svg')));
|
||||
matIconRegistry.addSvgIcon('application/vnd.openxmlformats-officedocument.wordprocessingml.template',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_ms_word.svg')));
|
||||
matIconRegistry.addSvgIcon('application/vnd.ms-powerpoint',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_ms_powerpoint.svg')));
|
||||
matIconRegistry.addSvgIcon('application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_ms_powerpoint.svg')));
|
||||
matIconRegistry.addSvgIcon('application/vnd.openxmlformats-officedocument.presentationml.template',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_ms_powerpoint.svg')));
|
||||
matIconRegistry.addSvgIcon('application/vnd.openxmlformats-officedocument.presentationml.slideshow',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_ms_powerpoint.svg')));
|
||||
matIconRegistry.addSvgIcon('video/mp4',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_video.svg')));
|
||||
matIconRegistry.addSvgIcon('text/plain',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_document.svg')));
|
||||
matIconRegistry.addSvgIcon('application/x-javascript',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_document.svg')));
|
||||
matIconRegistry.addSvgIcon('application/json',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_document.svg')));
|
||||
matIconRegistry.addSvgIcon('image/svg+xml',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_vector_image.svg')));
|
||||
matIconRegistry.addSvgIcon('text/html',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_website.svg')));
|
||||
matIconRegistry.addSvgIcon('application/x-compressed',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_archive.svg')));
|
||||
matIconRegistry.addSvgIcon('application/x-zip-compressed',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_archive.svg')));
|
||||
matIconRegistry.addSvgIcon('application/zip',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_archive.svg')));
|
||||
matIconRegistry.addSvgIcon('application/vnd.apple.keynote',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_presentation.svg')));
|
||||
matIconRegistry.addSvgIcon('application/vnd.apple.pages',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_document.svg')));
|
||||
matIconRegistry.addSvgIcon('application/vnd.apple.numbers',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_spreadsheet.svg')));
|
||||
matIconRegistry.addSvgIcon('folder',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_folder.svg')));
|
||||
matIconRegistry.addSvgIcon('disable/folder',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_folder_disable.svg')));
|
||||
matIconRegistry.addSvgIcon('selected',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_selected.svg')));
|
||||
matIconRegistry.addSvgIcon('default',
|
||||
sanitizer.bypassSecurityTrustResourceUrl(require('../assets/images/ft_ic_miscellaneous.svg')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get thumbnail URL for the given document node.
|
||||
* @param document Node to get URL for.
|
||||
* @returns {string} URL address.
|
||||
*/
|
||||
public getDocumentThumbnailUrl(document: any): string {
|
||||
let thumbnail = this.contentService.getDocumentThumbnailUrl(document);
|
||||
return thumbnail || this.DEFAULT_ICON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mimeType SVG
|
||||
* @param mimeType
|
||||
* @returns {string} URL SVG address.
|
||||
*/
|
||||
public getMimeTypeIcon(mimeType: string): string {
|
||||
let icon = this.mimeTypeIcons[mimeType];
|
||||
return (icon || this.DEFAULT_ICON);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default SVG
|
||||
* @returns {string} URL SVG default.
|
||||
*/
|
||||
public getDefaultMimeTypeIcon(): string {
|
||||
return this.DEFAULT_ICON;
|
||||
}
|
||||
}
|
138
lib/core/services/translate-loader.service.ts
Normal file
138
lib/core/services/translate-loader.service.ts
Normal file
@@ -0,0 +1,138 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { HttpClient } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Response } from '@angular/http';
|
||||
import { TranslateLoader } from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { ComponentTranslationModel } from '../models/component.model';
|
||||
import { ObjectUtils } from '../utils/object-utils';
|
||||
import { LogService } from './log.service';
|
||||
|
||||
@Injectable()
|
||||
export class TranslateLoaderService implements TranslateLoader {
|
||||
|
||||
private prefix: string = 'i18n';
|
||||
private suffix: string = '.json';
|
||||
private providers: ComponentTranslationModel[] = [];
|
||||
private queue: string [][] = [];
|
||||
|
||||
constructor(private http: HttpClient,
|
||||
private logService: LogService) {
|
||||
}
|
||||
|
||||
registerProvider(name: string, path: string) {
|
||||
let registered = this.providers.find(provider => provider.name === name);
|
||||
if (registered) {
|
||||
registered.path = path;
|
||||
} else {
|
||||
this.providers.push(new ComponentTranslationModel({ name: name, path: path }));
|
||||
}
|
||||
}
|
||||
|
||||
providerRegistered(name: string): boolean {
|
||||
return this.providers.find(x => x.name === name) ? true : false;
|
||||
}
|
||||
|
||||
getComponentToFetch(lang: string) {
|
||||
let observableBatch = [];
|
||||
if (!this.queue[lang]) {
|
||||
this.queue[lang] = [];
|
||||
}
|
||||
this.providers.forEach((component) => {
|
||||
if (!this.isComponentInQueue(lang, component.name)) {
|
||||
this.queue[lang].push(component.name);
|
||||
|
||||
let currentObserv = Observable.create(observer => {
|
||||
this.http.get(`${component.path}/${this.prefix}/${lang}${this.suffix}`)
|
||||
.map((res: Response) => {
|
||||
component.json[lang] = res;
|
||||
}).subscribe((result) => {
|
||||
observer.next(result);
|
||||
observer.complete();
|
||||
}, () => {
|
||||
observer.next('');
|
||||
observer.complete();
|
||||
});
|
||||
});
|
||||
|
||||
observableBatch.push(currentObserv);
|
||||
}
|
||||
});
|
||||
|
||||
return observableBatch;
|
||||
}
|
||||
|
||||
init(lang: string) {
|
||||
if (this.queue[lang] === undefined) {
|
||||
this.queue[lang] = [];
|
||||
}
|
||||
}
|
||||
|
||||
isComponentInQueue(lang: string, name: string) {
|
||||
return (this.queue[lang] || []).find(x => x === name) ? true : false;
|
||||
}
|
||||
|
||||
getFullTranslationJSON(lang: string): any {
|
||||
let result = {};
|
||||
|
||||
this.providers
|
||||
.slice(0)
|
||||
.sort((a, b) => {
|
||||
if (a.name === 'app') {
|
||||
return 1;
|
||||
}
|
||||
if (b.name === 'app') {
|
||||
return -1;
|
||||
}
|
||||
return a.name.localeCompare(b.name);
|
||||
})
|
||||
.forEach(model => {
|
||||
if (model.json && model.json[lang]) {
|
||||
result = ObjectUtils.merge(result, model.json[lang]);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
getTranslation(lang: string): Observable<any> {
|
||||
let observableBatch = this.getComponentToFetch(lang);
|
||||
|
||||
return Observable.create(observer => {
|
||||
if (observableBatch.length > 0) {
|
||||
Observable.forkJoin(observableBatch).subscribe(
|
||||
() => {
|
||||
let fullTranslation = this.getFullTranslationJSON(lang);
|
||||
if (fullTranslation) {
|
||||
observer.next(fullTranslation);
|
||||
}
|
||||
observer.complete();
|
||||
},
|
||||
(err: any) => {
|
||||
this.logService.error(err);
|
||||
});
|
||||
} else {
|
||||
let fullTranslation = this.getFullTranslationJSON(lang);
|
||||
if (fullTranslation) {
|
||||
observer.next(fullTranslation);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
106
lib/core/services/translate-loader.spec.ts
Normal file
106
lib/core/services/translate-loader.spec.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { HttpClientModule } from '@angular/common/http';
|
||||
import { Injector } from '@angular/core';
|
||||
import { getTestBed, TestBed } from '@angular/core/testing';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
|
||||
import { AlfrescoApiService } from '../services/alfresco-api.service';
|
||||
import { LogService } from './log.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { TRANSLATION_PROVIDER, TranslationService } from './translation.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
let componentJson1 = ' {"TEST": "This is a test", "TEST2": "This is another test"} ' ;
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
describe('TranslateLoader', () => {
|
||||
let injector: Injector;
|
||||
let translationService: TranslationService;
|
||||
let customLoader: TranslateLoaderService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
HttpClientModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
TranslationService,
|
||||
LogService,
|
||||
AlfrescoApiService,
|
||||
StorageService,
|
||||
UserPreferencesService,
|
||||
AppConfigService,
|
||||
{
|
||||
provide: TRANSLATION_PROVIDER,
|
||||
multi: true,
|
||||
useValue: {
|
||||
name: '@alfresco/core',
|
||||
source: 'assets/ng2-alfresco-core'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
injector = getTestBed();
|
||||
translationService = injector.get(TranslationService);
|
||||
customLoader = <TranslateLoaderService> translationService.translate.currentLoader;
|
||||
|
||||
jasmine.Ajax.install();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
it('should be able to provide any TranslateLoader', () => {
|
||||
expect(translationService).toBeDefined();
|
||||
expect(translationService.translate.currentLoader).toBeDefined();
|
||||
expect(translationService.translate.currentLoader instanceof TranslateLoaderService).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should add the component to the list', () => {
|
||||
customLoader.registerProvider('login', 'path/login');
|
||||
expect(customLoader.providerRegistered('login')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return the Json translation ', () => {
|
||||
customLoader.registerProvider('login', 'path/login');
|
||||
customLoader.getTranslation('en').subscribe(
|
||||
(response) => {
|
||||
expect(response).toBeDefined();
|
||||
expect(response).toEqual(JSON.parse(componentJson1));
|
||||
}
|
||||
);
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: componentJson1
|
||||
});
|
||||
});
|
||||
|
||||
});
|
106
lib/core/services/translation.service.spec.ts
Normal file
106
lib/core/services/translation.service.spec.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { HttpClientModule } from '@angular/common/http';
|
||||
import { Injector } from '@angular/core';
|
||||
import { getTestBed, TestBed } from '@angular/core/testing';
|
||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||
|
||||
import { AlfrescoApiService } from '../services/alfresco-api.service';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { LogService } from './log.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { TRANSLATION_PROVIDER, TranslationService } from './translation.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
describe('TranslationService', () => {
|
||||
let injector: Injector;
|
||||
let translationService: TranslationService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
HttpClientModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
TranslationService,
|
||||
LogService,
|
||||
AlfrescoApiService,
|
||||
StorageService,
|
||||
UserPreferencesService,
|
||||
AppConfigService,
|
||||
{
|
||||
provide: TRANSLATION_PROVIDER,
|
||||
multi: true,
|
||||
useValue: {
|
||||
name: '@alfresco/core',
|
||||
source: 'assets/ng2-alfresco-core'
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
jasmine.Ajax.install();
|
||||
|
||||
injector = getTestBed();
|
||||
translationService = injector.get(TranslationService);
|
||||
translationService.addTranslationFolder('fake-name', 'fake-path');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
it('is defined', () => {
|
||||
expect(translationService).toBeDefined();
|
||||
expect(translationService instanceof TranslationService).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should be able to get translations of the KEY: TEST', () => {
|
||||
translationService.get('TEST').subscribe((res: string) => {
|
||||
expect(res).toEqual('This is a test');
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'TEST': 'This is a test', 'TEST2': 'This is another test'})
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to get translations of the KEY: TEST2', () => {
|
||||
translationService.get('TEST2').subscribe((res: string) => {
|
||||
expect(res).toEqual('This is another test');
|
||||
});
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'application/json',
|
||||
responseText: JSON.stringify({'TEST': 'This is a test', 'TEST2': 'This is another test'})
|
||||
});
|
||||
});
|
||||
|
||||
});
|
86
lib/core/services/translation.service.ts
Normal file
86
lib/core/services/translation.service.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Inject, Injectable, InjectionToken, Optional } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
export const TRANSLATION_PROVIDER = new InjectionToken('Injection token for translation providers.');
|
||||
|
||||
export interface TranslationProvider {
|
||||
name: string;
|
||||
source: string;
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class TranslationService {
|
||||
defaultLang: string;
|
||||
userLang: string;
|
||||
customLoader: TranslateLoaderService;
|
||||
|
||||
constructor(public translate: TranslateService,
|
||||
private userPreference: UserPreferencesService,
|
||||
@Optional() @Inject(TRANSLATION_PROVIDER) providers: TranslationProvider[]) {
|
||||
this.customLoader = <TranslateLoaderService> this.translate.currentLoader;
|
||||
|
||||
this.defaultLang = 'en';
|
||||
translate.setDefaultLang(this.defaultLang);
|
||||
|
||||
if (providers && providers.length > 0) {
|
||||
for (let provider of providers) {
|
||||
this.addTranslationFolder(provider.name, provider.source);
|
||||
}
|
||||
}
|
||||
|
||||
this.userPreference.locale$.subscribe( (locale) => {
|
||||
this.userLang = locale;
|
||||
this.use(this.userLang);
|
||||
});
|
||||
}
|
||||
|
||||
addTranslationFolder(name: string = '', path: string = '') {
|
||||
if (!this.customLoader.providerRegistered(name)) {
|
||||
this.customLoader.registerProvider(name, path);
|
||||
if (this.userLang !== this.defaultLang) {
|
||||
this.translate.getTranslation(this.defaultLang).subscribe(() => {
|
||||
this.translate.getTranslation(this.userLang).subscribe(
|
||||
() => {
|
||||
this.translate.use(this.userLang);
|
||||
}
|
||||
);
|
||||
});
|
||||
} else {
|
||||
this.translate.getTranslation(this.userLang).subscribe(
|
||||
() => {
|
||||
this.translate.use(this.userLang);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use(lang: string): Observable<any> {
|
||||
this.customLoader.init(lang);
|
||||
return this.translate.use(lang);
|
||||
}
|
||||
|
||||
get(key: string|Array<string>, interpolateParams?: Object): Observable<string|any> {
|
||||
return this.translate.get(key, interpolateParams);
|
||||
}
|
||||
}
|
251
lib/core/services/upload.service.spec.ts
Normal file
251
lib/core/services/upload.service.spec.ts
Normal file
@@ -0,0 +1,251 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { EventEmitter } from '@angular/core';
|
||||
import { async, TestBed } from '@angular/core/testing';
|
||||
import { FileModel, FileUploadOptions, FileUploadStatus } from '../models/file.model';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { AppConfigModule } from '../app-config/app-config.module';
|
||||
import { AuthenticationService } from './authentication.service';
|
||||
import { StorageService } from './storage.service';
|
||||
import { UploadService } from './upload.service';
|
||||
|
||||
declare let jasmine: any;
|
||||
|
||||
describe('UploadService', () => {
|
||||
let service: UploadService;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppConfigModule
|
||||
],
|
||||
providers: [
|
||||
UploadService,
|
||||
AlfrescoApiService,
|
||||
SettingsService,
|
||||
AuthenticationService,
|
||||
StorageService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
let appConfig: AppConfigService = TestBed.get(AppConfigService);
|
||||
appConfig.config = {
|
||||
ecmHost: 'http://localhost:9876/ecm',
|
||||
files: {
|
||||
excluded: ['.DS_Store', 'desktop.ini', '.git', '*.git']
|
||||
}
|
||||
};
|
||||
|
||||
service = TestBed.get(UploadService);
|
||||
jasmine.Ajax.install();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jasmine.Ajax.uninstall();
|
||||
});
|
||||
|
||||
it('should return an empty queue if no elements are added', () => {
|
||||
expect(service.getQueue().length).toEqual(0);
|
||||
});
|
||||
|
||||
it('should add an element in the queue and returns it', () => {
|
||||
let filesFake = new FileModel(<File> { name: 'fake-name', size: 10 });
|
||||
service.addToQueue(filesFake);
|
||||
expect(service.getQueue().length).toEqual(1);
|
||||
});
|
||||
|
||||
it('should add two elements in the queue and returns them', () => {
|
||||
let filesFake = [
|
||||
new FileModel(<File> { name: 'fake-name', size: 10 }),
|
||||
new FileModel(<File> { name: 'fake-name2', size: 20 })
|
||||
];
|
||||
service.addToQueue(...filesFake);
|
||||
expect(service.getQueue().length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should skip hidden macOS files', () => {
|
||||
const file1 = new FileModel(new File([''], '.git'));
|
||||
const file2 = new FileModel(new File([''], 'readme.md'));
|
||||
const result = service.addToQueue(file1, file2);
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0]).toBe(file2);
|
||||
});
|
||||
|
||||
it('should make XHR done request after the file is added in the queue', (done) => {
|
||||
let emitter = new EventEmitter();
|
||||
|
||||
emitter.subscribe(e => {
|
||||
expect(e.value).toBe('File uploaded');
|
||||
done();
|
||||
});
|
||||
let fileFake = new FileModel(
|
||||
<File> { name: 'fake-name', size: 10 },
|
||||
<FileUploadOptions> { parentId: '-root-', path: 'fake-dir' }
|
||||
);
|
||||
service.addToQueue(fileFake);
|
||||
service.uploadFilesInTheQueue(emitter);
|
||||
|
||||
let request = jasmine.Ajax.requests.mostRecent();
|
||||
expect(request.url).toBe('http://localhost:9876/ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/-root-/children?autoRename=true');
|
||||
expect(request.method).toBe('POST');
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'text/plain',
|
||||
responseText: 'File uploaded'
|
||||
});
|
||||
});
|
||||
|
||||
it('should make XHR error request after an error occur', (done) => {
|
||||
let emitter = new EventEmitter();
|
||||
|
||||
emitter.subscribe(e => {
|
||||
expect(e.value).toBe('Error file uploaded');
|
||||
done();
|
||||
});
|
||||
let fileFake = new FileModel(
|
||||
<File> { name: 'fake-name', size: 10 },
|
||||
<FileUploadOptions> { parentId: '-root-' }
|
||||
);
|
||||
service.addToQueue(fileFake);
|
||||
service.uploadFilesInTheQueue(emitter);
|
||||
expect(jasmine.Ajax.requests.mostRecent().url)
|
||||
.toBe('http://localhost:9876/ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/-root-/children?autoRename=true');
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 404,
|
||||
contentType: 'text/plain',
|
||||
responseText: 'Error file uploaded'
|
||||
});
|
||||
});
|
||||
|
||||
it('should make XHR abort request after the xhr abort is called', (done) => {
|
||||
let emitter = new EventEmitter();
|
||||
|
||||
emitter.subscribe(e => {
|
||||
expect(e.value).toEqual('File aborted');
|
||||
done();
|
||||
});
|
||||
let fileFake = new FileModel(<File> { name: 'fake-name', size: 10 });
|
||||
service.addToQueue(fileFake);
|
||||
service.uploadFilesInTheQueue(emitter);
|
||||
|
||||
let file = service.getQueue();
|
||||
service.cancelUpload(...file);
|
||||
});
|
||||
|
||||
it('If versioning is true autoRename should not be present and majorVersion should be a param', () => {
|
||||
let emitter = new EventEmitter();
|
||||
|
||||
const filesFake = new FileModel(<File> { name: 'fake-name', size: 10 }, { newVersion: true });
|
||||
service.addToQueue(filesFake);
|
||||
service.uploadFilesInTheQueue(emitter);
|
||||
|
||||
expect(jasmine.Ajax.requests.mostRecent().url.endsWith('autoRename=true')).toBe(false);
|
||||
expect(jasmine.Ajax.requests.mostRecent().params.has('majorVersion')).toBe(true);
|
||||
});
|
||||
|
||||
it('should use custom root folder ID given to the service', (done) => {
|
||||
let emitter = new EventEmitter();
|
||||
|
||||
emitter.subscribe(e => {
|
||||
expect(e.value).toBe('File uploaded');
|
||||
done();
|
||||
});
|
||||
let filesFake = new FileModel(
|
||||
<File> { name: 'fake-name', size: 10 },
|
||||
<FileUploadOptions> { parentId: '123', path: 'fake-dir' }
|
||||
);
|
||||
service.addToQueue(filesFake);
|
||||
service.uploadFilesInTheQueue(emitter);
|
||||
|
||||
let request = jasmine.Ajax.requests.mostRecent();
|
||||
expect(request.url).toBe('http://localhost:9876/ecm/alfresco/api/-default-/public/alfresco/versions/1/nodes/123/children?autoRename=true');
|
||||
expect(request.method).toBe('POST');
|
||||
|
||||
jasmine.Ajax.requests.mostRecent().respondWith({
|
||||
'status': 200,
|
||||
contentType: 'text/plain',
|
||||
responseText: 'File uploaded'
|
||||
});
|
||||
});
|
||||
|
||||
it('should start downloading the next one if a file of the list is aborted', (done) => {
|
||||
let emitter = new EventEmitter();
|
||||
|
||||
service.fileUploadAborted.subscribe(e => {
|
||||
expect(e).not.toBeNull();
|
||||
});
|
||||
|
||||
service.fileUploadCancelled.subscribe(e => {
|
||||
expect(e).not.toBeNull();
|
||||
done();
|
||||
});
|
||||
|
||||
let fileFake1 = new FileModel(<File> { name: 'fake-name1', size: 10 });
|
||||
let fileFake2 = new FileModel(<File> { name: 'fake-name2', size: 10 });
|
||||
let filelist = [fileFake1, fileFake2];
|
||||
service.addToQueue(...filelist);
|
||||
service.uploadFilesInTheQueue(emitter);
|
||||
|
||||
let file = service.getQueue();
|
||||
service.cancelUpload(...file);
|
||||
});
|
||||
|
||||
it('should remove from the queue all the files in the exluded list', () => {
|
||||
const file1 = new FileModel(new File([''], '.git'));
|
||||
const file2 = new FileModel(new File([''], '.DS_Store'));
|
||||
const file3 = new FileModel(new File([''], 'desktop.ini'));
|
||||
const file4 = new FileModel(new File([''], 'readme.md'));
|
||||
const file5 = new FileModel(new File([''], 'test.git'));
|
||||
const result = service.addToQueue(file1, file2, file3, file4, file5);
|
||||
expect(result.length).toBe(1);
|
||||
expect(result[0]).toBe(file4);
|
||||
});
|
||||
|
||||
it('should call onUploadDeleted if file was deleted', () => {
|
||||
const file = <any> ({ status: FileUploadStatus.Deleted });
|
||||
spyOn(service.fileUploadDeleted, 'next');
|
||||
|
||||
service.cancelUpload(file);
|
||||
|
||||
expect(service.fileUploadDeleted.next).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call fileUploadError if file has error status', () => {
|
||||
const file = <any> ({ status: FileUploadStatus.Error });
|
||||
spyOn(service.fileUploadError, 'next');
|
||||
|
||||
service.cancelUpload(file);
|
||||
|
||||
expect(service.fileUploadError.next).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call fileUploadCancelled if file is in pending', () => {
|
||||
const file = <any> ({ status: FileUploadStatus.Pending });
|
||||
spyOn(service.fileUploadCancelled, 'next');
|
||||
|
||||
service.cancelUpload(file);
|
||||
|
||||
expect(service.fileUploadCancelled.next).toHaveBeenCalled();
|
||||
});
|
||||
});
|
294
lib/core/services/upload.service.ts
Normal file
294
lib/core/services/upload.service.ts
Normal file
@@ -0,0 +1,294 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { EventEmitter, Injectable } from '@angular/core';
|
||||
import * as minimatch from 'minimatch';
|
||||
import { Subject } from 'rxjs/Rx';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { FileUploadCompleteEvent, FileUploadDeleteEvent, FileUploadErrorEvent, FileUploadEvent } from '../events/file.event';
|
||||
import { FileModel, FileUploadProgress, FileUploadStatus } from '../models/file.model';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
|
||||
@Injectable()
|
||||
export class UploadService {
|
||||
|
||||
private queue: FileModel[] = [];
|
||||
private cache: { [key: string]: any } = {};
|
||||
private totalComplete: number = 0;
|
||||
private totalAborted: number = 0;
|
||||
private totalError: number = 0;
|
||||
private activeTask: Promise<any> = null;
|
||||
private excludedFileList: String[] = [];
|
||||
|
||||
queueChanged: Subject<FileModel[]> = new Subject<FileModel[]>();
|
||||
fileUpload: Subject<FileUploadEvent> = new Subject<FileUploadEvent>();
|
||||
fileUploadStarting: Subject<FileUploadEvent> = new Subject<FileUploadEvent>();
|
||||
fileUploadCancelled: Subject<FileUploadEvent> = new Subject<FileUploadEvent>();
|
||||
fileUploadProgress: Subject<FileUploadEvent> = new Subject<FileUploadEvent>();
|
||||
fileUploadAborted: Subject<FileUploadEvent> = new Subject<FileUploadEvent>();
|
||||
fileUploadError: Subject<FileUploadErrorEvent> = new Subject<FileUploadErrorEvent>();
|
||||
fileUploadComplete: Subject<FileUploadCompleteEvent> = new Subject<FileUploadCompleteEvent>();
|
||||
fileUploadDeleted: Subject<FileUploadDeleteEvent> = new Subject<FileUploadDeleteEvent>();
|
||||
fileDeleted: Subject<string> = new Subject<string>();
|
||||
|
||||
constructor(private apiService: AlfrescoApiService, private appConfigService: AppConfigService) {
|
||||
this.excludedFileList = <String[]> this.appConfigService.get('files.excluded');
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the service is uploading a file.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*
|
||||
* @memberof UploadService
|
||||
*/
|
||||
isUploading(): boolean {
|
||||
return this.activeTask ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the file Queue
|
||||
*
|
||||
* @return {FileModel[]} - files in the upload queue.
|
||||
*/
|
||||
getQueue(): FileModel[] {
|
||||
return this.queue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add files to the uploading queue to be uploaded.
|
||||
*
|
||||
* Examples:
|
||||
* addToQueue(file); // pass one file
|
||||
* addToQueue(file1, file2, file3); // pass multiple files
|
||||
* addToQueue(...[file1, file2, file3]); // pass an array of files
|
||||
*/
|
||||
addToQueue(...files: FileModel[]): FileModel[] {
|
||||
const allowedFiles = files.filter(f => this.filterElement(f));
|
||||
this.queue = this.queue.concat(allowedFiles);
|
||||
this.queueChanged.next(this.queue);
|
||||
return allowedFiles;
|
||||
}
|
||||
|
||||
private filterElement(file: FileModel) {
|
||||
let isAllowed = true;
|
||||
if (this.excludedFileList) {
|
||||
isAllowed = this.excludedFileList.filter(expr => minimatch(file.name, expr)).length === 0;
|
||||
}
|
||||
return isAllowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick all the files in the queue that are not been uploaded yet and upload it into the directory folder.
|
||||
*
|
||||
* @param {EventEmitter<any>} emitter @deprecated emitter to invoke on file status change
|
||||
*
|
||||
* @memberof UploadService
|
||||
*/
|
||||
uploadFilesInTheQueue(emitter: EventEmitter<any>): void {
|
||||
if (!this.activeTask) {
|
||||
let file = this.queue.find(f => f.status === FileUploadStatus.Pending);
|
||||
if (file) {
|
||||
this.onUploadStarting(file);
|
||||
|
||||
const promise = this.beginUpload(file, emitter);
|
||||
this.activeTask = promise;
|
||||
this.cache[file.id] = promise;
|
||||
|
||||
let next = () => {
|
||||
this.activeTask = null;
|
||||
setTimeout(() => this.uploadFilesInTheQueue(emitter), 100);
|
||||
};
|
||||
|
||||
promise.next = next;
|
||||
|
||||
promise.then(
|
||||
() => next(),
|
||||
() => next()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cancelUpload(...files: FileModel[]) {
|
||||
files.forEach(file => {
|
||||
const promise = this.cache[file.id];
|
||||
|
||||
if (promise) {
|
||||
promise.abort();
|
||||
delete this.cache[file.id];
|
||||
} else {
|
||||
const performAction = this.getAction(file);
|
||||
performAction();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
clearQueue() {
|
||||
this.queue = [];
|
||||
this.totalComplete = 0;
|
||||
this.totalAborted = 0;
|
||||
this.totalError = 0;
|
||||
}
|
||||
|
||||
getUploadPromise(file: FileModel) {
|
||||
let opts: any = {
|
||||
renditions: 'doclib'
|
||||
};
|
||||
|
||||
if (file.options.newVersion === true) {
|
||||
opts.overwrite = true;
|
||||
opts.majorVersion = true;
|
||||
} else {
|
||||
opts.autoRename = true;
|
||||
}
|
||||
return this.apiService.getInstance().upload.uploadFile(
|
||||
file.file,
|
||||
file.options.path,
|
||||
file.options.parentId,
|
||||
null,
|
||||
opts
|
||||
);
|
||||
}
|
||||
|
||||
private beginUpload(file: FileModel, /* @deprecated */emitter: EventEmitter<any>): any {
|
||||
|
||||
let promise = this.getUploadPromise(file);
|
||||
|
||||
promise.on('progress', (progress: FileUploadProgress) => {
|
||||
this.onUploadProgress(file, progress);
|
||||
})
|
||||
.on('abort', () => {
|
||||
this.onUploadAborted(file);
|
||||
emitter.emit({ value: 'File aborted' });
|
||||
})
|
||||
.on('error', err => {
|
||||
this.onUploadError(file, err);
|
||||
emitter.emit({ value: 'Error file uploaded' });
|
||||
})
|
||||
.on('success', data => {
|
||||
this.onUploadComplete(file, data);
|
||||
emitter.emit({ value: data });
|
||||
})
|
||||
.catch(err => {
|
||||
throw err;
|
||||
});
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
private onUploadStarting(file: FileModel): void {
|
||||
if (file) {
|
||||
file.status = FileUploadStatus.Starting;
|
||||
const event = new FileUploadEvent(file, FileUploadStatus.Starting);
|
||||
this.fileUpload.next(event);
|
||||
this.fileUploadStarting.next(event);
|
||||
}
|
||||
}
|
||||
|
||||
private onUploadProgress(file: FileModel, progress: FileUploadProgress): void {
|
||||
if (file) {
|
||||
file.progress = progress;
|
||||
file.status = FileUploadStatus.Progress;
|
||||
|
||||
const event = new FileUploadEvent(file, FileUploadStatus.Progress);
|
||||
this.fileUpload.next(event);
|
||||
this.fileUploadProgress.next(event);
|
||||
}
|
||||
}
|
||||
|
||||
private onUploadError(file: FileModel, error: any): void {
|
||||
if (file) {
|
||||
file.status = FileUploadStatus.Error;
|
||||
this.totalError++;
|
||||
|
||||
const promise = this.cache[file.id];
|
||||
if (promise) {
|
||||
delete this.cache[file.id];
|
||||
}
|
||||
|
||||
const event = new FileUploadErrorEvent(file, error, this.totalError);
|
||||
this.fileUpload.next(event);
|
||||
this.fileUploadError.next(event);
|
||||
}
|
||||
}
|
||||
|
||||
private onUploadComplete(file: FileModel, data: any): void {
|
||||
if (file) {
|
||||
file.status = FileUploadStatus.Complete;
|
||||
file.data = data;
|
||||
this.totalComplete++;
|
||||
|
||||
const promise = this.cache[file.id];
|
||||
if (promise) {
|
||||
delete this.cache[file.id];
|
||||
}
|
||||
|
||||
const event = new FileUploadCompleteEvent(file, this.totalComplete, data, this.totalAborted);
|
||||
this.fileUpload.next(event);
|
||||
this.fileUploadComplete.next(event);
|
||||
}
|
||||
}
|
||||
|
||||
private onUploadAborted(file: FileModel): void {
|
||||
if (file) {
|
||||
file.status = FileUploadStatus.Aborted;
|
||||
this.totalAborted++;
|
||||
|
||||
const promise = this.cache[file.id];
|
||||
if (promise) {
|
||||
delete this.cache[file.id];
|
||||
}
|
||||
|
||||
const event = new FileUploadEvent(file, FileUploadStatus.Aborted);
|
||||
this.fileUpload.next(event);
|
||||
this.fileUploadAborted.next(event);
|
||||
promise.next();
|
||||
}
|
||||
}
|
||||
|
||||
private onUploadCancelled(file: FileModel): void {
|
||||
if (file) {
|
||||
file.status = FileUploadStatus.Cancelled;
|
||||
|
||||
const event = new FileUploadEvent(file, FileUploadStatus.Cancelled);
|
||||
this.fileUpload.next(event);
|
||||
this.fileUploadCancelled.next(event);
|
||||
}
|
||||
}
|
||||
|
||||
private onUploadDeleted(file: FileModel): void {
|
||||
if (file) {
|
||||
file.status = FileUploadStatus.Deleted;
|
||||
this.totalComplete--;
|
||||
|
||||
const event = new FileUploadDeleteEvent(file, this.totalComplete);
|
||||
this.fileUpload.next(event);
|
||||
this.fileUploadDeleted.next(event);
|
||||
}
|
||||
}
|
||||
|
||||
private getAction(file) {
|
||||
const actions = {
|
||||
[FileUploadStatus.Pending]: () => this.onUploadCancelled(file),
|
||||
[FileUploadStatus.Deleted]: () => this.onUploadDeleted(file),
|
||||
[FileUploadStatus.Error]: () => this.onUploadError(file, null)
|
||||
};
|
||||
|
||||
return actions[file.status];
|
||||
}
|
||||
}
|
135
lib/core/services/user-preferences.service.spec.ts
Normal file
135
lib/core/services/user-preferences.service.spec.ts
Normal file
@@ -0,0 +1,135 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { async, TestBed } from '@angular/core/testing';
|
||||
import { TranslateLoader, TranslateModule, TranslateService } from '@ngx-translate/core';
|
||||
import { DirectiveModule } from '../directives';
|
||||
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { AppConfigModule } from '../app-config/app-config.module';
|
||||
import { StorageService } from './storage.service';
|
||||
import { TranslateLoaderService } from './translate-loader.service';
|
||||
import { UserPreferencesService } from './user-preferences.service';
|
||||
|
||||
describe('UserPreferencesService', () => {
|
||||
|
||||
const defaultPaginationSize: number = 10;
|
||||
let preferences: UserPreferencesService;
|
||||
let storage: StorageService;
|
||||
let appConfig: AppConfigService;
|
||||
let translate: TranslateService;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppConfigModule,
|
||||
DirectiveModule,
|
||||
TranslateModule.forRoot({
|
||||
loader: {
|
||||
provide: TranslateLoader,
|
||||
useClass: TranslateLoaderService
|
||||
}
|
||||
})
|
||||
],
|
||||
providers: [
|
||||
UserPreferencesService
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
appConfig = TestBed.get(AppConfigService);
|
||||
appConfig.config = {
|
||||
pagination: {
|
||||
size: 10
|
||||
}
|
||||
};
|
||||
preferences = TestBed.get(UserPreferencesService);
|
||||
storage = TestBed.get(StorageService);
|
||||
translate = TestBed.get(TranslateService);
|
||||
});
|
||||
|
||||
it('should get default pagination from app config', () => {
|
||||
expect(preferences.paginationSize).toBe(defaultPaginationSize);
|
||||
});
|
||||
|
||||
it('should use [GUEST] as default storage prefix', () => {
|
||||
expect(preferences.getStoragePrefix()).toBe('GUEST');
|
||||
});
|
||||
|
||||
it('should change storage prefix', () => {
|
||||
preferences.setStoragePrefix('USER_A');
|
||||
expect(preferences.getStoragePrefix()).toBe('USER_A');
|
||||
});
|
||||
|
||||
it('should format property key for default prefix', () => {
|
||||
preferences.setStoragePrefix(null);
|
||||
expect(preferences.getPropertyKey('propertyA')).toBe('GUEST__propertyA');
|
||||
});
|
||||
|
||||
it('should format property key for custom prefix', () => {
|
||||
preferences.setStoragePrefix('USER_A');
|
||||
expect(preferences.getPropertyKey('propertyA')).toBe('USER_A__propertyA');
|
||||
});
|
||||
|
||||
it('should save value with default prefix', () => {
|
||||
preferences.set('propertyA', 'valueA');
|
||||
const propertyKey = preferences.getPropertyKey('propertyA');
|
||||
expect(storage.getItem(propertyKey)).toBe('valueA');
|
||||
});
|
||||
|
||||
it('should save value with custom prefix', () => {
|
||||
preferences.setStoragePrefix('USER_A');
|
||||
preferences.set('propertyA', 'valueA');
|
||||
const propertyKey = preferences.getPropertyKey('propertyA');
|
||||
expect(storage.getItem(propertyKey)).toBe('valueA');
|
||||
});
|
||||
|
||||
it('should store custom pagination settings for default prefix', () => {
|
||||
preferences.paginationSize = 5;
|
||||
expect(preferences.paginationSize).toBe(5);
|
||||
});
|
||||
|
||||
it('should return default paginationSize value', () => {
|
||||
preferences.set('PAGINATION_SIZE', 0);
|
||||
expect(preferences.paginationSize).toBe(defaultPaginationSize);
|
||||
});
|
||||
|
||||
it('should return as default locale the app.config locate as first', () => {
|
||||
appConfig.config.locale = 'fake-locate-config';
|
||||
spyOn(translate, 'getBrowserLang').and.returnValue('fake-locate-browser');
|
||||
expect(preferences.getDefaultLocale()).toBe('fake-locate-config');
|
||||
});
|
||||
|
||||
it('should return as default locale the browser locale as second', () => {
|
||||
spyOn(translate, 'getBrowserLang').and.returnValue('fake-locate-browser');
|
||||
expect(preferences.getDefaultLocale()).toBe('fake-locate-browser');
|
||||
});
|
||||
|
||||
it('should return as default locale the component propery as third ', () => {
|
||||
spyOn(translate, 'getBrowserLang').and.stub();
|
||||
expect(preferences.getDefaultLocale()).toBe('en');
|
||||
});
|
||||
|
||||
it('should return as locale the store locate', () => {
|
||||
preferences.locale = 'fake-store-locate';
|
||||
appConfig.config.locale = 'fake-locate-config';
|
||||
spyOn(translate, 'getBrowserLang').and.returnValue('fake-locate-browser');
|
||||
expect(preferences.locale).toBe('fake-store-locate');
|
||||
});
|
||||
|
||||
});
|
119
lib/core/services/user-preferences.service.ts
Normal file
119
lib/core/services/user-preferences.service.ts
Normal file
@@ -0,0 +1,119 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 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 { Injectable } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
import { AppConfigService } from '../app-config/app-config.service';
|
||||
import { AlfrescoApiService } from './alfresco-api.service';
|
||||
import { StorageService } from './storage.service';
|
||||
|
||||
@Injectable()
|
||||
export class UserPreferencesService {
|
||||
|
||||
private defaults = {
|
||||
paginationSize: 25,
|
||||
locale: 'en'
|
||||
};
|
||||
|
||||
private localeSubject: BehaviorSubject<string> ;
|
||||
locale$: Observable<string>;
|
||||
|
||||
constructor(
|
||||
public translate: TranslateService,
|
||||
private appConfig: AppConfigService,
|
||||
private storage: StorageService,
|
||||
private apiService: AlfrescoApiService
|
||||
) {
|
||||
const currentLocale = this.locale || this.getDefaultLocale();
|
||||
this.localeSubject = new BehaviorSubject(currentLocale);
|
||||
this.locale$ = this.localeSubject.asObservable();
|
||||
this.defaults.paginationSize = appConfig.get('pagination.size', 25);
|
||||
}
|
||||
|
||||
get(property: string, defaultValue?: string): string {
|
||||
const key = this.getPropertyKey(property);
|
||||
const value = this.storage.getItem(key);
|
||||
if (value === undefined) {
|
||||
return defaultValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
set(property: string, value: any) {
|
||||
if (!property) { return; }
|
||||
|
||||
this.storage.setItem(
|
||||
this.getPropertyKey(property),
|
||||
value
|
||||
);
|
||||
}
|
||||
|
||||
getStoragePrefix(): string {
|
||||
return this.storage.getItem('USER_PROFILE') || 'GUEST';
|
||||
}
|
||||
|
||||
setStoragePrefix(value: string) {
|
||||
this.storage.setItem('USER_PROFILE', value || 'GUEST');
|
||||
}
|
||||
|
||||
getPropertyKey(property: string): string {
|
||||
return `${this.getStoragePrefix()}__${property}`;
|
||||
}
|
||||
|
||||
set authType(value: string) {
|
||||
this.storage.setItem('AUTH_TYPE', value);
|
||||
this.apiService.reset();
|
||||
}
|
||||
|
||||
get authType(): string {
|
||||
return this.storage.getItem('AUTH_TYPE') || 'ALL';
|
||||
}
|
||||
|
||||
set disableCSRF(value: boolean) {
|
||||
this.set('DISABLE_CSRF', value);
|
||||
this.apiService.reset();
|
||||
}
|
||||
|
||||
get disableCSRF(): boolean {
|
||||
return this.get('DISABLE_CSRF') === 'true';
|
||||
}
|
||||
|
||||
set paginationSize(value: number) {
|
||||
this.set('PAGINATION_SIZE', value);
|
||||
}
|
||||
|
||||
get paginationSize(): number {
|
||||
return Number(this.get('PAGINATION_SIZE')) || this.defaults.paginationSize;
|
||||
}
|
||||
|
||||
get locale(): string {
|
||||
const locale = this.get('LOCALE');
|
||||
return locale;
|
||||
}
|
||||
|
||||
set locale(value: string) {
|
||||
this.localeSubject.next(value);
|
||||
this.set('LOCALE', value);
|
||||
}
|
||||
|
||||
public getDefaultLocale(): string {
|
||||
return this.appConfig.get<string>('locale') || this.translate.getBrowserLang() || 'en';
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user