Added slices
Change-Id: I9dfaa9348fa82da844a04c0c2a58ce07e9fa3a28
diff --git a/src/app/services/helpers/store.service.spec.ts b/src/app/services/helpers/store.service.spec.ts
new file mode 100644
index 0000000..d70d649
--- /dev/null
+++ b/src/app/services/helpers/store.service.spec.ts
@@ -0,0 +1,88 @@
+
+import {ObservableCollectionHandler} from './store.service';
+import {IWSEvent} from '../../interfaces/ws.interface';
+import {BehaviorSubject} from 'rxjs';
+
+describe('Service: Observable Collection Handler', () => {
+
+ let subject: BehaviorSubject<any>;
+ let observable;
+
+ beforeEach(() => {
+ subject = new BehaviorSubject([]);
+ observable = subject.asObservable();
+ });
+
+ it('Should have an update method', () => {
+ expect(ObservableCollectionHandler.update).toBeDefined();
+ });
+
+ it('should add an element to the observable', (done) => {
+ const event: IWSEvent = {
+ model: 'Test',
+ msg: {
+ pk: 1,
+ changed_fields: [],
+ object: {id: 1, foo: 'bar'}
+ }
+ };
+
+ ObservableCollectionHandler.update(event, subject);
+
+ subject.subscribe(
+ (collection: any[]) => {
+ expect(collection.length).toBe(1);
+ expect(collection[0].foo).toEqual('bar');
+ done();
+ }
+ );
+ });
+
+ describe('when the subject already have content', () => {
+ beforeEach(() => {
+ subject.next([{id: 1, foo: 'bar'}, {id: 2, foo: 'baz'}]);
+ });
+
+ it('should update an element', (done) => {
+ const event: IWSEvent = {
+ model: 'Test',
+ msg: {
+ pk: 1,
+ changed_fields: [],
+ object: {id: 1, foo: 'updated'}
+ }
+ };
+
+ ObservableCollectionHandler.update(event, subject);
+
+ subject.subscribe(
+ (collection: any[]) => {
+ expect(collection.length).toBe(2);
+ expect(collection[0].foo).toEqual('updated');
+ done();
+ }
+ );
+ });
+
+ it('should delete an element', (done) => {
+ const event: IWSEvent = {
+ model: 'Test',
+ msg: {
+ pk: 1,
+ changed_fields: ['deleted'],
+ object: {id: 1, foo: 'deleted'}
+ }
+ };
+
+ ObservableCollectionHandler.update(event, subject);
+
+ subject.subscribe(
+ (collection: any[]) => {
+ expect(collection.length).toBe(1);
+ expect(collection[0].foo).toEqual('baz');
+ done();
+ }
+ );
+ });
+ });
+});
diff --git a/src/app/services/helpers/store.service.ts b/src/app/services/helpers/store.service.ts
new file mode 100644
index 0000000..80e8e05
--- /dev/null
+++ b/src/app/services/helpers/store.service.ts
@@ -0,0 +1,40 @@
+import {Injectable} from '@angular/core';
+import {IWSEvent} from '../../interfaces/ws.interface';
+import {BehaviorSubject} from 'rxjs';
+import * as _ from 'lodash';
+
+/**
+ * @whatItDoes Update a BehaviorSubject after receiving an event from an Observable
+ * @stable
+ */
+
+@Injectable()
+export class ObservableCollectionHandler {
+
+ static update(event: IWSEvent, subject: BehaviorSubject<any>): BehaviorSubject<any> {
+ const collection: any[] = subject.value;
+
+ const index: number = _.findIndex(collection, (i) => {
+ return i.id === event.msg.object.id;
+ });
+ const exist: boolean = index > -1;
+ const isDeleted: boolean = _.includes(event.msg.changed_fields, 'deleted');
+
+ // remove
+ if (exist && isDeleted) {
+ _.remove(collection, {id: event.msg.object.id});
+ }
+ // Replace item at index using native splice
+ else if (exist && !isDeleted) {
+ collection.splice(index, 1, event.msg.object);
+ }
+ // if the element is not deleted add it
+ else if (!exist && !isDeleted) {
+ collection.push(event.msg.object);
+ }
+
+ subject.next(collection);
+
+ return subject;
+ }
+}
diff --git a/src/app/services/rest/auth.service.ts b/src/app/services/rest/auth.service.ts
index b5b00fb..978825f 100644
--- a/src/app/services/rest/auth.service.ts
+++ b/src/app/services/rest/auth.service.ts
@@ -2,7 +2,7 @@
// Imports
import {AppConfig} from '../../config/app.config';
-import {Injectable} from '@angular/core';
+import {Injectable} from '@angular/core';
import {Http, Response, Headers} from '@angular/http';
import {Observable} from 'rxjs/Rx';
import {IAuthRequest, IAuthResponse} from '../../interfaces/auth.interface';
@@ -28,13 +28,35 @@
}
// get auth info to authenticate API
- getUserHeaders(): Headers{
+ getUserHeaders(): Headers {
const headers = new Headers();
headers.append('x-csrftoken', this.cookieService.get('xoscsrftoken'));
headers.append('x-sessionid', this.cookieService.get('xossessionid'));
return headers;
}
+ // log the user in
+ login(auth: IAuthRequest): Observable<IAuthResponse> {
+ return this.http.post(`${AppConfig.apiEndpoint}/utility/login/`, auth)
+ .map((res: Response) => res.json())
+ .map((auth: IAuthResponse) => {
+ this.storeAuth(auth);
+ auth.user = JSON.parse(auth.user);
+ return auth;
+ })
+ .catch((error: any) => Observable.throw(error.json().error || 'Server error'));
+ }
+
+ // logout the user
+ logout(): Observable<any> {
+ return this.http.post(`${AppConfig.apiEndpoint}/utility/logout/`, {xossessionid: this.xosSessionId})
+ .map((res: Response) => {
+ this.removeAuth();
+ return res.text();
+ })
+ .catch((error: any) => Observable.throw(error.json().error || 'Server error'));
+ }
+
// save cookies
private storeAuth(auth: IAuthResponse): void {
this.cookieService.put('xoscsrftoken', auth.xoscsrftoken);
@@ -46,27 +68,5 @@
this.cookieService.remove('xoscsrftoken');
this.cookieService.remove('xossessionid');
}
-
- // log the user in
- login(auth: IAuthRequest): Observable<IAuthResponse> {
- return this.http.post(`${AppConfig.apiEndpoint}/utility/login/`, auth)
- .map((res: Response) => res.json())
- .map((auth: IAuthResponse) => {
- this.storeAuth(auth);
- auth.user = JSON.parse(auth.user);
- return auth;
- })
- .catch((error:any) => Observable.throw(error.json().error || 'Server error'));
- }
-
- // logout the user
- logout(): Observable<any> {
- return this.http.post(`${AppConfig.apiEndpoint}/utility/logout/`, {xossessionid: this.xosSessionId})
- .map((res: Response) => {
- this.removeAuth();
- return res.text();
- })
- .catch((error: any) => Observable.throw(error.json().error || 'Server error'));
- }
}
diff --git a/src/app/services/rest/core.service.ts b/src/app/services/rest/core.service.ts
index 3890c47..a283024 100644
--- a/src/app/services/rest/core.service.ts
+++ b/src/app/services/rest/core.service.ts
@@ -20,7 +20,7 @@
constructor (private http: XosHttp) {}
// Fetch all existing comments
- getCoreEndpoints() : Observable<any[]> {
+ getCoreEndpoints(): Observable<any[]> {
const search = 'some=param';
@@ -29,7 +29,7 @@
// ...and calling .json() on the response to return data
.map((res: Response) => res.json())
// ...errors if any
- .catch((error:any) => Observable.throw(error.json().error || 'Server error'));
+ .catch((error: any) => Observable.throw(error.json().error || 'Server error'));
}
}
diff --git a/src/app/services/rest/instance.service.ts b/src/app/services/rest/instance.service.ts
index c864e54..899b484 100644
--- a/src/app/services/rest/instance.service.ts
+++ b/src/app/services/rest/instance.service.ts
@@ -3,8 +3,8 @@
// Imports
import {AppConfig} from '../../config/app.config';
import {AuthService} from './auth.service';
-import { Injectable } from '@angular/core';
-import { Http, Response, Headers } from '@angular/http';
+import {Injectable} from '@angular/core';
+import {Response} from '@angular/http';
import {XosHttp} from './xoshttp.service';
import {Observable} from 'rxjs/Rx';
diff --git a/src/app/services/rest/slices.service.ts b/src/app/services/rest/slices.service.ts
new file mode 100644
index 0000000..2b71d7a
--- /dev/null
+++ b/src/app/services/rest/slices.service.ts
@@ -0,0 +1,24 @@
+/// <reference path="../../../../typings/index.d.ts"/>
+
+// Imports
+import {AppConfig} from '../../config/app.config';
+import { Injectable } from '@angular/core';
+import { Response} from '@angular/http';
+import {XosHttp} from './xoshttp.service';
+import {Observable} from 'rxjs/Rx';
+
+// Import RxJs required methods
+import 'rxjs/add/operator/map';
+import 'rxjs/add/operator/catch';
+
+@Injectable()
+export class SliceService {
+ private baseUrl = AppConfig.apiEndpoint;
+ constructor (private http: XosHttp) {}
+ // Fetch all existing instances
+ query() : Observable<any[]> {
+ return this.http.get(`${this.baseUrl}/core/slices/`)
+ .map((res: Response) => res.json())
+ .catch((error: any) => Observable.throw(error.response.json().error || 'Server error'));
+ }
+}
diff --git a/src/app/services/rest/xoshttp.service.ts b/src/app/services/rest/xoshttp.service.ts
index 5572683..a300ee3 100644
--- a/src/app/services/rest/xoshttp.service.ts
+++ b/src/app/services/rest/xoshttp.service.ts
@@ -13,9 +13,20 @@
) {
}
+ // TODO intercept non authenticated calls and send to login (remove cookies)
+ // TODO add POST, PUT, DELETE declaration
+ get(url: string, options?: RequestOptionsArgs): Observable<Response> {
+
+ options = this.checkOptions(options);
+ options = this.getHeaders(options);
+ options = this.getParams(options);
+
+ return this.http.get(url, options);
+ }
+
private checkOptions(options?: RequestOptionsArgs): RequestOptionsArgs {
// if options are not there, create them
- if(!options){
+ if (!options) {
options = {};
}
return options;
@@ -41,15 +52,4 @@
}
return options;
}
-
- get(url: string, options?: RequestOptionsArgs): Observable<Response> {
-
- options = this.checkOptions(options);
- options = this.getHeaders(options);
- options = this.getParams(options);
-
- return this.http.get(url, options)
- }
-
- // TODO add POST, PUT, DELETE declaration
}
diff --git a/src/app/services/stores/instance.store.ts b/src/app/services/stores/instance.store.ts
index a87630c..9a07095 100644
--- a/src/app/services/stores/instance.store.ts
+++ b/src/app/services/stores/instance.store.ts
@@ -2,11 +2,11 @@
import {Injectable} from '@angular/core';
import {BehaviorSubject} from 'rxjs/Rx';
-import {IInstance} from '../../interfaces/instance.interface';
+import {IInstance} from '../../interfaces/models.interface';
import {InstanceService} from '../rest/instance.service';
-import * as _ from 'lodash';
import {IWSEvent} from '../../interfaces/ws.interface';
import {GlobalEvent} from '../websockets/websocket.global';
+import {ObservableCollectionHandler} from '../helpers/store.service';
@Injectable()
export class InstanceStore {
@@ -14,25 +14,10 @@
constructor(private instanceService: InstanceService, private globalEvent: GlobalEvent) {
this.loadInitialData();
this.globalEvent.list()
- .filter((e: IWSEvent) => {
- console.log('filter', e);
- return e.model === 'Instance';
- })
+ .filter((e: IWSEvent) => e.model === 'Instance')
.subscribe(
(event: IWSEvent) => {
-
- const collection = this._instances.value;
-
- const exist = _.find(collection, (i) => {
- return i.id === event.msg.object.id;
- });
-
- // remove in order to update
- if (exist) {
- _.remove(collection, {id: event.msg.object.id});
- }
- collection.push(event.msg.object);
- this._instances.next(collection);
+ ObservableCollectionHandler.update(event, this._instances);
}
);
}
diff --git a/src/app/services/stores/slice.store.ts b/src/app/services/stores/slice.store.ts
new file mode 100644
index 0000000..aeab9f3
--- /dev/null
+++ b/src/app/services/stores/slice.store.ts
@@ -0,0 +1,39 @@
+/// <reference path="../../../../typings/index.d.ts"/>
+
+import {Injectable} from '@angular/core';
+import {BehaviorSubject} from 'rxjs/Rx';
+import {ISlice} from '../../interfaces/models.interface';
+import {IWSEvent} from '../../interfaces/ws.interface';
+import {GlobalEvent} from '../websockets/websocket.global';
+import {SliceService} from '../rest/slices.service';
+import {ObservableCollectionHandler} from '../helpers/store.service';
+
+@Injectable()
+export class SliceStore {
+ private _slices: BehaviorSubject<ISlice[]> = new BehaviorSubject([]);
+ constructor(private sliceService: SliceService, private globalEvent: GlobalEvent) {
+ this.loadInitialData();
+ this.globalEvent.list()
+ .filter((e: IWSEvent) => e.model === 'Slice')
+ .subscribe(
+ (event: IWSEvent) => {
+ ObservableCollectionHandler.update(event, this._slices);
+ }
+ );
+ }
+
+ loadInitialData() {
+ this.sliceService.query()
+ .subscribe(
+ res => {
+ this._slices.next(res);
+ },
+ err => console.log('Error retrieving Instances', err)
+ );
+ }
+
+ query() {
+ return this._slices.asObservable();
+ }
+
+}
diff --git a/src/app/services/websockets/websocket.global.ts b/src/app/services/websockets/websocket.global.ts
index ee62c12..46bfbe1 100644
--- a/src/app/services/websockets/websocket.global.ts
+++ b/src/app/services/websockets/websocket.global.ts
@@ -1,29 +1,23 @@
/// <reference path="../../../../typings/index.d.ts"/>
import {Injectable} from '@angular/core';
-import {BehaviorSubject} from 'rxjs/Rx';
+import {Subject} from 'rxjs/Rx';
import * as io from 'socket.io-client';
import {AppConfig} from '../../config/app.config';
import {IWSEvent} from '../../interfaces/ws.interface';
@Injectable()
export class GlobalEvent {
- private _events: BehaviorSubject<IWSEvent> = new BehaviorSubject<IWSEvent>({
- model: 'XOS',
- msg: {
- changed_fields: []
- }
- });
+ private _events: Subject<IWSEvent> = new Subject<IWSEvent>();
private socket;
constructor() {
this.socket = io(AppConfig.websocketClient);
- this.socket.on('event', (data: IWSEvent) => {
+ this.socket.on('event', (data: IWSEvent): void => {
+ console.log('event', data);
this._events.next(data);
});
}
-
list() {
return this._events.asObservable();
}
-
}