Creating Stores and using Observables
Change-Id: I214692e64df065beaddee0e0ec8759de540c269d
diff --git a/src/app/datasources/helpers/store.helpers.ts b/src/app/datasources/helpers/store.helpers.ts
new file mode 100644
index 0000000..dfb1e7a
--- /dev/null
+++ b/src/app/datasources/helpers/store.helpers.ts
@@ -0,0 +1,34 @@
+import {BehaviorSubject} from 'rxjs';
+import * as _ from 'lodash';
+import {IWSEvent} from '../websocket/global';
+
+export interface IStoreHelpersService {
+ updateCollection(event: IWSEvent, subject: BehaviorSubject<any>): BehaviorSubject<any>;
+}
+
+export class StoreHelpers {
+ public updateCollection(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/datasources/index.ts b/src/app/datasources/index.ts
new file mode 100644
index 0000000..4473541
--- /dev/null
+++ b/src/app/datasources/index.ts
@@ -0,0 +1,20 @@
+import {CoreRest} from './rest/core.rest';
+import {SlicesRest} from './rest/slices.rest';
+import {AuthService} from './rest/auth.rest';
+import {WebSocketEvent} from './websocket/global';
+import {SliceStore} from './stores/slices.store';
+import {StoreHelpers} from './helpers/store.helpers';
+
+export const xosRest = 'xosDataSources';
+
+angular
+ .module('xosDataSources', ['ngCookies'])
+ .service('CoreRest', CoreRest)
+ .service('SlicesRest', SlicesRest)
+ .service('AuthService', AuthService)
+ .service('WebSocket', WebSocketEvent);
+
+angular
+ .module('xosDataSources')
+ .service('StoreHelpers', StoreHelpers)
+ .service('SlicesStore', SliceStore);
diff --git a/src/app/datasources/rest/auth.rest.ts b/src/app/datasources/rest/auth.rest.ts
new file mode 100644
index 0000000..a94599a
--- /dev/null
+++ b/src/app/datasources/rest/auth.rest.ts
@@ -0,0 +1,41 @@
+import {AppConfig} from '../../config/app.config';
+import IHttpPromiseCallbackArg = angular.IHttpPromiseCallbackArg;
+export interface IAuthRequestData {
+ username: string;
+ password: string;
+}
+
+export interface IAuthResponseData extends IHttpPromiseCallbackArg<any> {
+ data: {
+ user: string;
+ xoscsrftoken: string;
+ xossessionid: string;
+ };
+}
+export class AuthService {
+
+
+ /** @ngInject */
+ constructor(
+ private $http: angular.IHttpService,
+ private $q: angular.IQService,
+ private $cookies: angular.cookies.ICookiesService
+ ) {
+ }
+
+ public login(data: IAuthRequestData): Promise<any> {
+ const d = this.$q.defer();
+ this.$http.post(`${AppConfig.apiEndpoint}/utility/login/`, data)
+ .then((res: IAuthResponseData) => {
+ this.$cookies.put('xoscsrftoken', res.data.xoscsrftoken);
+ this.$cookies.put('xossessionid', res.data.xossessionid);
+ this.$cookies.put('xosuser', res.data.user);
+ res.data.user = JSON.parse(res.data.user);
+ d.resolve(res.data);
+ })
+ .catch(e => {
+ d.reject(e);
+ });
+ return d.promise;
+ }
+}
diff --git a/src/app/datasources/rest/core.rest.ts b/src/app/datasources/rest/core.rest.ts
new file mode 100644
index 0000000..2c10e10
--- /dev/null
+++ b/src/app/datasources/rest/core.rest.ts
@@ -0,0 +1,18 @@
+import {AppConfig} from '../../config/app.config';
+export class CoreRest {
+
+ /** @ngInject */
+ constructor(
+ private $http: angular.IHttpService,
+ private $q: angular.IQService
+ ) {
+ }
+
+ public query(): Promise<any> {
+ const d = this.$q.defer();
+ this.$http.get(`${AppConfig.apiEndpoint}/core/`)
+ .then(res => d.resolve(res.data))
+ .catch(d.reject);
+ return d.promise;
+ }
+}
diff --git a/src/app/datasources/rest/slices.rest.ts b/src/app/datasources/rest/slices.rest.ts
new file mode 100644
index 0000000..a5b7e5c
--- /dev/null
+++ b/src/app/datasources/rest/slices.rest.ts
@@ -0,0 +1,21 @@
+import {AppConfig} from '../../config/app.config';
+
+export interface IXosResourceService {
+ getResource(): ng.resource.IResourceClass<any>;
+}
+
+export class SlicesRest implements IXosResourceService {
+ static $inject = ['$resource'];
+ private resource: angular.resource.IResourceClass<any>;
+
+ /** @ngInject */
+ constructor(
+ private $resource: ng.resource.IResourceService
+ ) {
+ this.resource = this.$resource(`${AppConfig.apiEndpoint}/core/slices/`);
+ }
+
+ public getResource(): ng.resource.IResourceClass<ng.resource.IResource<any>> {
+ return this.resource;
+ }
+}
diff --git a/src/app/datasources/stores/slices.store.ts b/src/app/datasources/stores/slices.store.ts
new file mode 100644
index 0000000..9c3389f
--- /dev/null
+++ b/src/app/datasources/stores/slices.store.ts
@@ -0,0 +1,43 @@
+/// <reference path="../../../../typings/index.d.ts"/>
+
+import {BehaviorSubject, Observable} from 'rxjs/Rx';
+import {IWSEvent, IWSEventService} from '../websocket/global';
+import {IXosResourceService} from '../rest/slices.rest';
+import {IStoreHelpersService} from '../helpers/store.helpers';
+
+export interface IStoreService {
+ query(): Observable<any>;
+}
+
+export class SliceStore {
+ static $inject = ['WebSocket', 'StoreHelpers', 'SlicesRest'];
+ private _slices: BehaviorSubject<any[]> = new BehaviorSubject([]);
+ constructor(
+ private webSocket: IWSEventService,
+ private storeHelpers: IStoreHelpersService,
+ private sliceService: IXosResourceService
+ ) {
+ this.loadInitialData();
+ this.webSocket.list()
+ .filter((e: IWSEvent) => e.model === 'Slice')
+ .subscribe(
+ (event: IWSEvent) => {
+ this.storeHelpers.updateCollection(event, this._slices);
+ }
+ );
+ }
+
+ query() {
+ return this._slices.asObservable();
+ }
+
+ private loadInitialData() {
+ this.sliceService.getResource().query().$promise
+ .then(
+ res => {
+ this._slices.next(res);
+ },
+ err => console.log('Error retrieving Slices', err)
+ );
+ }
+}
diff --git a/src/app/datasources/websocket/global.ts b/src/app/datasources/websocket/global.ts
new file mode 100644
index 0000000..aaf142a
--- /dev/null
+++ b/src/app/datasources/websocket/global.ts
@@ -0,0 +1,31 @@
+import * as io from 'socket.io-client';
+import {Subject, Observable} from 'rxjs/Rx';
+import {AppConfig} from '../../config/app.config';
+
+export interface IWSEvent {
+ model: string;
+ msg: {
+ changed_fields: string[],
+ object?: any,
+ pk?: number
+ };
+}
+
+export interface IWSEventService {
+ list(): Observable<IWSEvent>;
+}
+
+export class WebSocketEvent {
+ private _events: Subject<IWSEvent> = new Subject<IWSEvent>();
+ private socket;
+ constructor() {
+ console.log('socket.io');
+ this.socket = io(AppConfig.websocketClient);
+ this.socket.on('event', (data: IWSEvent): void => {
+ this._events.next(data);
+ });
+ }
+ list() {
+ return this._events.asObservable();
+ }
+}